Django biginger自动递增字段作为主键?

2024-04-28 22:21:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在建设一个项目,涉及到很多集体智慧。访问该网站的每个用户都会创建一个唯一的配置文件,然后他们的数据将用于计算自己和其他用户的最佳匹配。

默认情况下,Django创建一个INT(11)id字段来处理模型主键。我担心这会很快被溢出(即大约24亿个设备在没有事先设置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字段那样自动递增呢?另外,我可以让它无符号,这样我就有更多的空间来填写吗?

谢谢!


Tags: 数据项目django用户模型id网站models
3条回答

NOTE: This answer as modified, according to Larry's code. Previous solution extended fields.BigIntegerField, but better to extend 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"])

很明显,这对南部移民来说效果不错。

如果您使用的是Django 1.10,Django现在内置了一个bigatofield:

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

注意,我不是扩展bigingerfield,而是扩展AutoField。这是一个重要的区别。使用AutoField,Django将从数据库中检索自动递增的id,而biginger则不会。

从bigingerfield更改为AutoField时的一个问题是在AutoField中将数据转换为int。

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

相关问题 更多 >