Andrew
Andrew

Reputation: 1040

Django creates pointless migrations on choices list change

I'm trying to create a model with a choices field using a callable, so that Django doesn't create migrations when a choices list changes, as stated in this question here.

class Quote(models.Model):
    severity = models.IntegerField(choices=get_severity_choices)
    ...

class get_severity_choices(object):
    def __iter__(self):
        for item in SEVERITY_CHOICES:
            yield item

where

SEVERITY_CHOICES = (
    (1, 'Low'),
    (2, 'Medium'),
    (3, 'High'),
)

However, I'm getting an error message:

quoting.Quote.severity: (fields.E004) 'choices' must be an iterable (e.g., a list or tuple).

Upvotes: 2

Views: 2056

Answers (1)

solarissmoke
solarissmoke

Reputation: 31474

I think you're mixing up the choices argument on a Model field, and that on a forms.ChoiceField field. In a model, choices must be an interable - you cannot pass a callable:

choices: An iterable (e.g., a list or tuple) consisting itself of iterables of exactly two items (e.g. [(A, B), (A, B) ...]) to use as choices for this field.

Your get_severity_choices class isn't being recognised as an iterable because Django expects it to subclass collections.Iterable rather than just expose an __iter__ method.

You can pass a callable to a FormField:

choices: Either an iterable (e.g., a list or tuple) of 2-tuples to use as choices for this field, or a callable that returns such an iterable.

For a Model field however you must specify your choices beforehand. Also from the docs:

Note that choices can be any iterable object – not necessarily a list or tuple. This lets you construct choices dynamically. But if you find yourself hacking choices to be dynamic, you’re probably better off using a proper database table with a ForeignKey. choices is meant for static data that doesn’t change much, if ever.

As regards why Django creates the seemingly useless migrations, there is some discussion about that in this ticket:

This is by design. There are several reasons, not least of which ... that datamigrations at points in history need to have a full accurate representation of the models, including all their options, not just those which affect the database.

Upvotes: 6

Related Questions