If you have custom code for models (custom validators and custom fields are examples), Django Migrations will import them directly into the migration files. An example:

file web/models.py

def validate_power(self, power):
    if power == 'fly':
        raise ValidationError('Heroes cannot fly!')

class Hero(Model):
    power = CharField(max_length=30, validators=[validate_power])

In the migration file, there will be:

file web/migrations/0001_initial.py

class Migration(migrations.Migration):

    operations = [
                ('id', models.AutoField(verbose_name='ID', serialize=False, primary_key=True, auto_created=True)),
                ('power', models.CharField(max_length=30, validators=[web.models.validate_power])),

The validator is imported directly from the codebase. What this means is that if I ever change a validator, I have to make sure it is backwards-compatible, for as long as I keep that migration (which could be forever). Same happens to custom fields, which is worse to keep backwards-compatibility because sometimes you need to change (or just want to change) how you store data, handle it, etc. If you change how you store data, for example, it could make sense the change the validators and then all the previous migrations that relied on the validator will not work anymore (unless you change the migration code, and that could be many files, and also changing migration code should not be needed).

So, this idea of directly importing from the codebase binds data to code. Shouldn't we strive to keep them separate? Maybe we should stick to raw SQL migrations? Is this problem possible to be solved without using raw SQL migrations? Is binding data to code a price worth paying to keep SQL at a distance?

  • This question should be on StackOverflow, as it is a specific question about an individual library. Nevertheless, the answer is absolutely clearly given in the Django documentation: the migrations library constructs a representation of the models separate from your models code itself, and you always use that. Your assertion is plainly false. – Daniel Roseman Nov 16 '15 at 19:09
  • 1
    I politely disagree. First, I'm not discussing here the take of Django on the solution, but rather why they chose this solution and if there's a way to avoid the problem at all. Second, why don't you test what I'm saying? If you can change how you storage data in every possible context without the need to mess with old migrations files, then yes I'm wrong. Sadly, I don't think that's the case. – jpmelos Nov 16 '15 at 20:14

This is addressed in the Migrations overview of the Django documentation. You can remove obsolete references after squashing migrations.

| improve this answer | |
  • I don't think the documentation addresses the problem. It just states we can remove obsolete references after squashing migrations. It doesn't solve the data-bound-to-code problem (if that's even possible without raw SQL migrations). – jpmelos Nov 16 '15 at 17:13
  • 1
    Yes, this is the design of the migrations framework. Unfortunately I can't do much more than to point at talks by Andrew Godwin which discusses some of the design decisions. I'm not sure if you'll find an answer to your question though. Andrew Godwin about Django migrations at Django: Under The Hood: youtube.com/watch?v=-4jhPRfCRSM and Andrew Godwin: Designing Django's Migrations - PyCon 2014: youtube.com/watch?v=a-_GAHfpk1Y – Tim Graham Nov 21 '15 at 16:09
  • Thank you for pointing out the videos, Tim! I'll watch them. – jpmelos Nov 22 '15 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.