Thursday, February 26, 2015

Re: Migrations force me to have, forever, any name/reference I use in field validators=, choices=, whatever, valid forever (even if the requirements change).

Yes, it's expected behavior. Please see the documentation on the topic:
https://docs.djangoproject.com/en/stable/topics/migrations/#historical-models

On Wednesday, February 25, 2015 at 3:25:19 PM UTC-5, Luis Masuelli wrote:
I have an issue with migrations.

Suppose I declare (in my application, with name myapp) a field with a validators= declared. In such value (which is an iterable), I declare a function:

class MyModel(models.Model):
   
"""
    This one is identifiable.
    """


    identifier
= models.CharField(max_length=10, unique=True, validators=[valid_identifier])

Assume I created the migration with makemigrations:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
from django.conf import settings
import django.core.validators
import micnt.models


class Migration(migrations.Migration):

    dependencies
= [
       
...
   
]

    operations
= [
        migrations
.CreateModel(
            name
='MyModel',
            fields
=[
               
('identifier', models.CharField(max_length=10, unique=True, validators=[myapp.models.valid_identifier])),
           
],
            options
={
           
},
            bases
=(models.Model,),
       
),
   
]

Assume valid_identifier is any external callable which will take one positional argument, and eventually raise ValidationError under certain conditions.

Now the requirements vary: The identifier may be national or foreign, so the country is required as an additional field, and also a discriminator field. Additionally, the validation I must perform is cross-field, so instead of using something in validators, I define a clean() method, and make the combination of country/identifier unique, instead of just the identifier unique:

class MyModel(models.Model):
   
"""
    This one is identifiable.
    """


    identifier_type = models.CharField(max_length=10, choices=(('passport', _(u'Passport')), ('national', _(u'National'))), null=False)
    identifier
= models.CharField(max_length=10)
    country = models.ForeignKey(Country, null=False)  # assume Country model exists

    class Meta:
        unique_together = (('identifier', 'country'),)

    def clean(self):
        raise ValidationError('Implement this!')
   

And then, I don't need anymore the valid_identifier function, since my code does not use it anymore. So I delete it.

Now I will create the migration with makemigrations as usual. What will happen?

a. The command will succeed.
b. The command will explode (i. e. a normal Python exception).
c. The command will create an inconsistent migration, without exploding.
d. Jesus will come again.
e. The command will get into a kind of endless loop.

If you guesses "b", you were right. Django will report an error, since myapp.models.valid_identifier does not exist anymore (AttributeError).

So, once I set a value for validators= parameter and create a migration, I am forced to keep such reference valid for the rest of my life (e.g. by having valid_identifier=None, if I don't need the function anymore), or else the migrations will not work again since they will be traversed, imported, and will get such AttributeError.

Is this an expected, normal, behavior?

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/aa3cc60a-50e2-4be6-a430-0ae1d351e2b5%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment