如果不向用户显示,在 Django 模型中使用 IntegerChoices 字段是否有优势?

Are there advantages to using IntegerChoices field in a Django model if it's not shown to users?

我在我的 Django (3.2) 模型中使用 IntegerChoices

class AType(db.IntegerChoices):
    UNKNOWN = 0, 'Unknown'
    SOMETHING = 1, 'Something'
    ANOTHER_THING = 2, 'Another thing'
    A_THIRD_THING = 3, 'A third thing'


class MyObject(models.Model):
    a_type = db.IntegerField(choices=AType.choices)

(我已将选项更改为更通用。)

每次我给AType加一个值,它都会产生一个数据库迁移,我忠实地应用它。

a_type 完全在幕后。用户永远看不到它,所以它只在管理员 UI 中,但我不需要它是可编辑的。所以表格并没有真正被使用。

这些迁移对数据库有什么影响(例如约束)吗?

考虑到 IntegerChoices 字段不显示给(非工作人员)用户且不显示在表单中,是否还有其他实用程序?

如果没有实用程序,我正在考虑将 MyObject.a_type 更改为 IntegerField,并继续在任何地方使用 AType,但不会进行所有迁移。

Is there any impact on the DB (e.g., constraints) of these migrations?

对架构没有影响。你可以在 python manage.py sqlmigrate myapp 000x_mymigration.

中看到这个

然而,它仍然CREATE TABLEINSERT INTO ... SELECT(昂贵)、DROP TABLEALTER TABLE

这是“设计使然”和“不会修复”的:

Is there any other utility to having an IntegerChoices field, given that it's not displayed to a (non-staff) user, and not in a form?

是,模型验证。
参考:https://docs.djangoproject.com/en/3.2/ref/models/fields/#choices

I'm thinking of just changing MyObject.a_type to an IntegerField, and continuing to use AType everywhere, but not having all the migrations.

您可以通过在 makemigrationsmigrate 中修补 MigrationAutodetector 来忽略 choices

您还可以忽略 _verbose_namehelp_text

mysite/apps.py:

from django.apps import AppConfig
from django.core.management.commands import makemigrations, migrate
from django.db import models
from django.db.migrations import autodetector


class MigrationAutodetector(autodetector.MigrationAutodetector):
    ignored_field_attribute_names = [
        'choices',
        # '_verbose_name',
        # 'help_text',
    ]

    def deep_deconstruct(self, obj):
        if isinstance(obj, models.Field):
            for attr_name in self.ignored_field_attribute_names:
                setattr(obj, attr_name, None)
        return super().deep_deconstruct(obj)


class MySiteAppConfig(AppConfig):
    name = 'mysite'

    def ready(self):
        makemigrations.MigrationAutodetector = MigrationAutodetector
        migrate.MigrationAutodetector = MigrationAutodetector
        pass

mysite/settings.py:

INSTALLED_APPS = [
    # ...
    'mysite.apps.MySiteAppConfig',
]