Поле автоматического приращения 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) и юг.