如果不向用户显示,在 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 TABLE
、INSERT INTO ... SELECT
(昂贵)、DROP TABLE
、ALTER TABLE
。
这是“设计使然”和“不会修复”的:
- #22837 (Migrations detect unnessecary(?) changes) — Django
- #30048 (Migrations created when verbose_name or help_text is changed) – Django
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.
您可以通过在 makemigrations
和 migrate
中修补 MigrationAutodetector
来忽略 choices
。
您还可以忽略 _verbose_name
和 help_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',
]
我在我的 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 TABLE
、INSERT INTO ... SELECT
(昂贵)、DROP TABLE
、ALTER TABLE
。
这是“设计使然”和“不会修复”的:
- #22837 (Migrations detect unnessecary(?) changes) — Django
- #30048 (Migrations created when verbose_name or help_text is changed) – Django
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 useAType
everywhere, but not having all the migrations.
您可以通过在 makemigrations
和 migrate
中修补 MigrationAutodetector
来忽略 choices
。
您还可以忽略 _verbose_name
和 help_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',
]