Django BigInteger 自动增量字段作为主键?

发布于 2024-08-30 05:09:32 字数 597 浏览 11 评论 0 原文

我目前正在构建一个涉及大量集体智慧的项目。每个访问网站的用户都会创建一个独特的个人资料,他们的数据随后用于计算自己和其他用户的最佳匹配。

默认情况下,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 字段一样?另外,我可以将其设为未签名,以便有更多空间来填写吗?

谢谢!

I'm currently building a project which involves a lot of collective intelligence. Every user visiting the web site gets created a unique profile and their data is later used to calculate best matches for themselves and other users.

By default, Django creates an INT(11) id field to handle models primary keys. I'm concerned with this being overflown very quickly (i.e. ~2.4b devices visiting the page without prior cookie set up). How can I change it to be represented as BIGINT in MySQL and long() inside Django itself?

I've found I could do the following (http://docs.djangoproject.com/en/dev/ref/models/fields/#bigintegerfield):

class MyProfile(models.Model):
    id = BigIntegerField(primary_key=True)

But is there a way to make it autoincrement, like usual id fields? Additionally, can I make it unsigned so that I get more space to fill in?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

拍不死你 2024-09-06 05:09:32

如果您使用 Django 1.10,Django 现在内置了 BigAutoField:

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

Django now has a BigAutoField built in if you are using Django 1.10:

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

无言温柔 2024-09-06 05:09:32

受到 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 将从数据库中检索自动递增的 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 不会截断数字,也不会更改基础类型。

Inspired by lfagundes but with a small but important correction:

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

Notice instead of extending BigIntegerField, I am extending AutoField. This is an important distinction. With AutoField, Django will retrieve the AUTO INCREMENTed id from the database, whereas BigInteger will not.

One concern when changing from BigIntegerField to AutoField was the casting of the data to an int in AutoField.

Notice from 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)

and

def get_prep_value(self, value):
    if value is None:
        return None
    return int(value)

It turns out this is OK, as verified in a python shell:

>>> l2 = 99999999999999999999999999999
>>> type(l2)
<type 'long'>
>>> int(l2)
99999999999999999999999999999L
>>> type(l2)
<type 'long'>
>>> type(int(l2))
<type 'long'>

In other words, casting to an int will not truncate the number, nor will it change the underlying type.

独木成林 2024-09-06 05:09:32

注意:根据 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"])

显然,这对于南方迁移来说工作得很好。

NOTE: This answer as modified, according to Larry's code. Previous solution extended fields.BigIntegerField, but better to extend fields.AutoField

I had the same problem and solved with following code:

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

Apparently this is working fine with south migrations.

贱人配狗天长地久 2024-09-06 05:09:32

从 Django 3.2 开始,可以使用 DEFAULT_AUTO_FIELD 设置(文档)。因此,不再需要覆盖所有模型中的主键。

#This setting will change all implicitly added primary keys to BigAutoField
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

请注意,从 Django 3.2 开始,生成的新项目的 DEFAULT_AUTO_FIELD 设置为 BigAutoField (发行说明)。

Since Django 3.2 the type of implicit primary key can be controlled with the DEFAULT_AUTO_FIELD setting (documentation). So, there is no need anymore to override primary keys in all your models.

#This setting will change all implicitly added primary keys to BigAutoField
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

Note that starting with Django 3.2 new projects are generated with DEFAULT_AUTO_FIELD set to BigAutoField (release notes).

ペ泪落弦音 2024-09-06 05:09:32

您可以稍后更改该表。这可能是一个更好的解决方案。

You could alter the table afterwards. That may be a better solution.

半夏半凉 2024-09-06 05:09:32

如前所述,您可以事后更改该表。这是一个很好的解决方案。

为了不忘记这一点,您可以在应用程序包下创建一个管理模块并使用 post_syncdb 信号。

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

这可能会导致 django-admin.py 刷新失败。但这仍然是我所知道的最好的选择。

As stated before you could alter the table afterwards. That is a good solution.

To do that without forgetting, you can create a management module under your application package and use the post_syncdb signal.

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

This can cause django-admin.py flush to fail. But it is still the best alternative I know.

耀眼的星火 2024-09-06 05:09:32

我也有同样的问题。看起来 django 中不支持 BigInteger 自动字段。

我尝试创建一些自定义字段 BigIntegerAutoField 但我遇到了南迁移系统的问题(南无法为我的字段创建序列)。

在尝试了几种不同的方法之后,我决定遵循 Matthew 的建议并进行更改表(例如 postgre 中的 ALTER TABLE table_name ALTER COLUMN id TYPE bigint;) 如果

有 django 支持的解决方案(例如建于 BigIntegerAutoField) 和南部。

I also had the same problem. Looks like there is no support for BigInteger auto fields in django.

I've tried to create some custom field BigIntegerAutoField but I faced a problem with south migration system (south couldn't create sequence for my field).

After giving a try couple of different approaches I decided to follow Matthew's advice and do alter table (e.g. ALTER TABLE table_name ALTER COLUMN id TYPE bigint; in postgre)

Would be great to have solution supported by django (like built in BigIntegerAutoField) and south.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文