我目前正在建立一个涉及大量集体智慧的项目。每个访问该网站的用户都会创建一个独特的个人资料,他们的数据稍后会用于为自己和其他用户计算最佳匹配。
默认情况下,Django创建一个INT(11)id
字段来处理模型主键。我担心这种情况很快就会溢出(即〜2.4b设备访问该页面而没有事先设置cookie)。如何将其更改为在MySQL中表示为BIGINT,在Django本身中表示为long()?
我发现我可以执行以下操作(http://docs.djangoproject.com/en/dev/ref/models/fields/#bigintegerfield):
class MyProfile(models.Model):
id = BigIntegerField(primary_key=True)
但有没有办法让它自动增量,就像通常的id
字段一样?另外,我可以将它设为无符号,以便我可以填充更多空间吗?
谢谢!
答案 0 :(得分:17)
受到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时的一个问题是将数据转换为AutoField中的int。
来自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 shell中验证的那样:
>>> l2 = 99999999999999999999999999999
>>> type(l2)
<type 'long'>
>>> int(l2)
99999999999999999999999999999L
>>> type(l2)
<type 'long'>
>>> type(int(l2))
<type 'long'>
换句话说,转换为int不会截断数字,也不会更改基础类型。
答案 1 :(得分:14)
注意:根据Larry的代码,此答案已修改。以前的解决方案扩展了fields.BigIntegerField,但更好地扩展fields.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"])
显然这对南方迁移来说很好。
答案 2 :(得分:8)
如果您使用Django 1.10,Django现在内置了BigAutoField:
https://docs.djangoproject.com/en/1.10/ref/models/fields/#bigautofield
答案 3 :(得分:6)
之后您可以更改表格。这可能是一个更好的解决方案。
答案 4 :(得分:3)
如前所述,您之后可以更改表格。这是一个很好的解决方案。
为了做到这一点而不忘记,您可以在应用程序包下创建一个管理模块并使用post_syncdb信号。
https://docs.djangoproject.com/en/dev/ref/signals/#post-syncdb
这可能导致django-admin.py刷新失败。但它仍然是我所知道的最佳选择。
答案 5 :(得分:2)
我也有同样的问题。看起来django中不支持BigInteger自动字段。
我尝试创建一些自定义字段BigIntegerAutoField但是我遇到了南迁移系统的问题(南方无法为我的字段创建序列)。
在尝试了几种不同的方法后,我决定遵循马修的建议并改变表格(例如postgre中的ALTER TABLE table_name ALTER COLUMN id TYPE bigint;
)
django(如内置BigIntegerAutoField)和南方支持解决方案会很棒。