I'm using IntegerChoices
in my Django (3.2) model.
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)
(I've changed the choices to be more generic.)
Every time I add a value to AType, it produces a DB migration, which I faithfully apply.
a_type
is strictly behind the scenes. Users never see it, so it's only in the admin UI, but I don't need it to be editable. So forms aren't really used.
Is there any impact on the DB (e.g., constraints) of these migrations?
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?
If there's no utility, I'm thinking of just changing MyObject.a_type
to an IntegerField, and continuing to use AType
everywhere, but not having all the migrations.
CodePudding user response:
Is there any impact on the DB (e.g., constraints) of these migrations?
No impact to the schema. You can see this in python manage.py sqlmigrate myapp 000x_mymigration
.
However, it still does CREATE TABLE
, INSERT INTO ... SELECT
(expensive), DROP TABLE
, ALTER TABLE
.
This is "by design" and "wontfix":
- #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?
Yes, model validation.
Reference: 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.
You can ignore choices
by patching MigrationAutodetector
in makemigrations
and migrate
.
You can additionally ignore _verbose_name
and 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',
]