Description
Code of Conduct
- I agree to follow Django's Code of Conduct
Feature Description
When using Django's Choices
in model field choices, there should be a mechanism to avoid migrations updating each time the Choices
enum changes.
Problem
Given:
class Customer(models.Model):
class TaxCode(models.TextChoices):
TAX = 'TAX', 'Tax'
EXEMPT = 'EXEMPT', 'Exempt'
taxcode = models.CharField(max_length=6, choices=TaxCode.choices)
Each time i change my enum, django will generate a fresh migration:
migrations.AlterField(
model_name='customer',
name='taxcode',
field=models.CharField(choices=[('TAX', 'Tax'), ('EXEMPT', 'Exempt'), ('BLAH', ...)], max_length=6),
),
There should be a way to indicate to django that migrations don't need updating.
Request or proposal
proposal
Additional Details
Original discussion here.
The current way around this issue, which is only possible since dj5, is to define a separate function for each Choices enum, and pass that to model choices..
def get_taxcode_choices():
return Customer.TaxCode.choices
class Customer(models.Model):
class TaxCode(models.TextChoices):
TAX = 'TAX', 'Tax'
EXEMPT = 'EXEMPT', 'Exempt'
taxcode = models.CharField(max_length=6, choices=get_taxcode_choices)
This gets repetitive and noisy very quickly.
Implementation Suggestions
There were some early thoughts to have migration generator handle this magically (ie not unfurl .choices
prematurely if a django Choices
is detected), however to avoid magic or cause backwards compatibility issues, the more sensible approach is probs to just introduce an explicit callable classmethod on the Choices
model.
I propose we add a model_choices
method:
class Choices(enum.Enum, metaclass=ChoicesType):
@classmethod
def model_choices(cls):
return cls.choices
...
Users can then do this:
class Customer(models.Model):
class TaxCode(models.TextChoices):
TAX = 'TAX', 'Tax'
EXEMPT = 'EXEMPT', 'Exempt'
taxcode = models.CharField(max_length=6, choices=TaxCode.model_choices)
which results in migrations generating out like this initially (and not generating new operations from thereon):
migrations.CreateModel(
name='Customer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('taxcode', models.CharField(choices=Customer.TaxCode.model_choices, max_length=6)),
],
),
Credits to @bayangan1991 for initial idea.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status