Подтвердить что ты не робот

Поле auto-increment Django BigInteger в качестве первичного ключа?

В настоящее время я строил проект, который включает в себя много коллективного интеллекта. Каждый пользователь, посещающий веб-сайт, получает уникальный профиль, и их данные позже используются для расчета наилучших совпадений для себя и других пользователей.

По умолчанию Django создает поле INT (11) id для обработки первичных ключей моделей. Я обеспокоен тем, что это очень быстро переполнено (то есть ~ 2.4b устройств, посещающих страницу без предварительной настройки cookie). Как я могу изменить его для представления как BIGINT в MySQL и long() внутри самого Django?

Я обнаружил, что могу сделать следующее (http://docs.djangoproject.com/en/dev/ref/models/fields/#bigintegerfield):

class MyProfile(models.Model):
    id = BigIntegerField(primary_key=True)

Но есть ли способ сделать это автоинкремент, как обычные поля id? Кроме того, могу ли я сделать это без знака, чтобы получить больше места для заполнения?

Спасибо!

4b9b3361

Ответ 2

Вдохновленный lfagundes, но с небольшой, но важной коррекцией:

class BigAutoField(fields.AutoField):
    def db_type(self, connection):  # pylint: disable=W0621
        if 'mysql' in connection.__class__.__module__:
            return 'bigint AUTO_INCREMENT'
        return super(BigAutoField, self).db_type(connection)

add_introspection_rules([], [r"^a\.b\.c\.BigAutoField"])

Обратите внимание, что вместо расширения BigIntegerField я расширяю AutoField. Это важное различие. С помощью AutoField Django будет извлекать AUTO INCREMENTed id из базы данных, тогда как BigInteger не будет.

Одна из проблем при переходе с BigIntegerField на AutoField заключалась в литье данных в int в AutoField.

Уведомление от Django AutoField:

def to_python(self, value):
    if value is None:
        return value
    try:
        return int(value)
    except (TypeError, ValueError):
        msg = self.error_messages['invalid'] % str(value)
        raise exceptions.ValidationError(msg)

и

def get_prep_value(self, value):
    if value is None:
        return None
    return int(value)

Оказывается, это нормально, как проверено в оболочке python:

>>> l2 = 99999999999999999999999999999
>>> type(l2)
<type 'long'>
>>> int(l2)
99999999999999999999999999999L
>>> type(l2)
<type 'long'>
>>> type(int(l2))
<type 'long'>

Другими словами, приведение к int не приведет к усечению числа и не изменяет базовый тип.

Ответ 3

ПРИМЕЧАНИЕ. Этот ответ изменен, согласно коду Ларри. Предыдущее решение расширенных полей .BigIntegerField, но лучше расширять поля .AutoField

У меня была та же проблема и решена с помощью следующего кода:

from django.db.models import fields
from south.modelsinspector import add_introspection_rules

class BigAutoField(fields.AutoField):
    def db_type(self, connection):
        if 'mysql' in connection.__class__.__module__:
            return 'bigint AUTO_INCREMENT'
        return super(BigAutoField, self).db_type(connection)

add_introspection_rules([], ["^MYAPP\.fields\.BigAutoField"])

По-видимому, это прекрасно работает с южными миграциями.

Ответ 4

После этого вы можете изменить таблицу. Это может быть лучшим решением.

Ответ 5

Как указано выше, вы можете впоследствии изменить таблицу. Это хорошее решение.

Чтобы сделать это без забвения, вы можете создать модуль управления в своем пакете приложений и использовать сигнал post_syncdb.

https://docs.djangoproject.com/en/dev/ref/signals/#post-syncdb

Это может привести к сбою django-admin.py. Но это все еще лучшая альтернатива, которую я знаю.

Ответ 6

У меня также была та же проблема. Похоже, что нет поддержки для автоматических полей BigInteger в django.

Я попытался создать какое-то настраиваемое поле BigIntegerAutoField, но у меня возникла проблема с южной миграционной системой (юг не мог создать последовательность для моего поля).

Попробовав несколько разных подходов, я решил следовать совету Мэттью и изменить таблицу (например, ALTER TABLE table_name ALTER COLUMN id TYPE bigint; в postgre)

Было бы здорово иметь решение, поддерживаемое django (например, встроенным BigIntegerAutoField) и югом.