Поле автоматического приращения Django BigInteger в качестве первичного ключа?

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

по умолчанию Django создает INT (11) id поле для обработки первичных ключей моделей. Я обеспокоен тем, что это очень быстро переполняется (т. е. ~2.4 B устройства, посещающие страницу без предварительной настройки 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 полей? Кроме того, могу ли я сделать его неподписанным, чтобы получить больше места для заполнения?

спасибо!

6 ответов


Django теперь имеет встроенное BigAutoField, если вы используете Django 1.10:

https://docs.djangoproject.com/en/1.10/ref/models/fields/#bigautofield


вдохновленный 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 будет извлекать автоматически увеличенный идентификатор из базы данных, в то время как BigInteger не будет.

одной из проблем при переходе от BigIntegerField к AutoField было приведение данных к int в 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 не усечет число и не изменит базовый тип.


Примечание: этот ответ изменен в соответствии с кодом Ларри. Расширенные поля предыдущего решения.BigIntegerField, но лучше расширить поля.Автополе, о

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

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"])

по-видимому, это отлично работает с Южной миграцией.


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


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

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

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

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


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

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

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

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