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

Time:09-27

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":

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 use AType 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',
]
  • Related