Improve Choices for migrations
- Dominant language
- No language data
- Stars
- 188
- Forks
- 7
- PR merge metrics
- No merged PRs in 30d
Description
### Code of Conduct
- [x] 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:
```python
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:
```python
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](https://forum.djangoproject.com/t/migration-optimizer-does-not-optimize-choices/4645).
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..
```python
def get_taxcode_choices():
return Customer.TaxCode.choices
```
```python
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:
```python
class Choices(enum.Enum, metaclass=ChoicesType):
@classmethod
def model_choices(cls):
return cls.choices
...
```
Users can then do this:
```python
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):
```python
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.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.