Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django detecting redundant migrations repetitively

Tags:

python

django

Background

We are working in Python3.4 / Django1.8.4 and we are witnessing a strange phenomenon with respect to our user model, and specifically the timezone field of this model.

Every so often when we are making migrations the new migration file will include an operation to alter said timezone field, but all of the attributes that are included in the operation are already set to the same values that the migration is trying to assign!

There are 3 such fields and they are:

1) default - with the value of "UTC"

2) max_length - with the value of 30, and

3) choices - a very long array of tuples containing time zone names/values.

It looks like:

choices=[('Africa/Abidjan', 'Africa/Abidjan'), ('Africa/Accra', 'Africa/Accra'), ('Africa/Addis_Ababa', 'Africa/Addis_Ababa'), ... ]

The migration operation always wants to set these 3 properties of the timezone field to the exact same 3 corresponding values, even though they are already set to such values! It is essentially a redundant, useless operation.

Sometimes when we run makemigrations there will be no changes to the app, except to this silly field!

Questions

1) Why is this happening?

2) How do we prevent this? It's annoying that the app thinks migrations are needed when they aren't.

Extra Info

While the same 3 properties of the field are always set to the exact same values, the order that they appear in the operation seems to be non-deterministic (likely because django uses unordered dict instances to store the data which is used to generate the migration file).

The choices field, as we define it in our model, is dynamically generated when the app is initially run. The (boiled-down) code looks like this:

class MyUser(models.Model):
    f_name = models.CharField(max_length=32398) # Gotta accomodate those crazy south-eastern names haha
    l_name = models.CharField(max_length=94823)

    # ...
    # more fields and stuff etc.
    # ...

    time_zone = models.CharField(default="UTC", choices=TIMEZONE_CHOICES, max_length=30)

The important part there is that choices=TIMEZONE_CHOICES, which is defined earlier as such:

import pytz
TIMEZONE_CHOICES = ()
for time_zone in pytz.common_timezones:
    TIMEZONE_CHOICES += ((time_zone, time_zone),)

Just including this information in case it turns out to be relevant.

like image 476
Gershom Maes Avatar asked Jan 07 '16 19:01

Gershom Maes


People also ask

What does Makemigrations do in Django?

makemigrations is responsible for packaging up your model changes into individual migration files - analogous to commits - and migrate is responsible for applying those to your database.

What is difference between migrate and migration in Django?

So the difference between makemigrations and migrate is this: makemigrations auto generates migration files containing changes that need to be applied to the database, but doesn't actually change anyhting in your database. migrate will make the actual modifications to your database, based on the migration files.

How do I undo migrations in Django?

By doing python manage.py migrate app B (or A; both works) . Remove the migration files A and Y for time being from the project location. Now unapply B, by doing python manage.py migrate app X .


1 Answers

You could try using an existing package that will allow you to use a time zone directly as a model field.

https://pypi.python.org/pypi/django-timezone-field/

class MyModel(models.Model):
    timezone1 = TimeZoneField(default='Europe/London') # defaults supported
like image 63
Alex Carlos Avatar answered Oct 29 '22 14:10

Alex Carlos