受 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 不会截断数字,也不会更改基础类型。