[Django]-Ignore changes in CharField "choices" during Django migration creation

2👍

It turns out this is not enabled for a reason (from this answer)

This is by design. There are several reasons, not least of which for me 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.

However, you can go back to the initial migration and do

class Migration(migrations.Migration):
    operations = [
        migrations.CreateModel(
            name='owner',
            fields=[
                ('city', models.CharField(choices=settings.CITIES, blank=True, max_length=3, db_index=True)),
    ]

Not very pretty and it could theoretically come back to bite you down the line, so refactoring with a ForeignKey and select_related('cities') in the get_queryset() in the manager might be the safest/least-hacky way to go about this, but this should never result in a new migration happening with a settings change that results in a choices change.

1👍

I wouldn’t make it that difficult on me to validate everything database/ORM wise, but do the validating in the controller/the form.

Here’s what I would do building upon your sample code:

models.py:

class Owner(models.Model):
    city = models.CharField(
        verbose_name=u'City', max_length=255, blank=True, db_index=True
    )

(No choices here!)

views.py:

class CitySelectionView(FormView):
    template_name = "city_selection.html"
    form_class = forms.CitySelectionForm

     def form_valid(self, form):
         obj = models.Owner(city=form.cleaned_data['city']
         obj.save()
         return redirect('index')

forms.py:

class CitySelectionForm(forms.Form):
    city = forms.MultipleChoiceField(choices=settings.CITIES)

If cities now is

CITIES = (('dusseldorf', 'Düsseldorf, Germany'), ('berlin', 'Berlin, Germany'))

the form will show Düsseldorf and Berlin, and if it’s

CITIES = (('london', 'London, UK'), ('paris', 'Paris, France'))

the form will show London and Paris.

Leave a comment