3

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 = [
        migrations.CreateModel(
            name='Hero',
            fields=[
                ('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?

2
  • 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. Nov 16, 2015 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, 2015 at 20:14

1 Answer 1

2

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

3
  • 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, 2015 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, 2015 at 16:09
  • Thank you for pointing out the videos, Tim! I'll watch them.
    – jpmelos
    Nov 22, 2015 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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