Back in the days of South migrations, if you wanted to create a custom model field that extended a Django field's functionality, you could tell South to use the introspection rules of the parent class like so:
from south.modelsinspector import add_introspection_rules add_introspection_rules([], ["^myapp\.stuff\.fields\.SomeNewField"])
Now that migrations have been moved to Django, is there a non-South equivalent of the above? Is an equivalent even needed anymore, or is the new migration stuff smart enough to just figure it out on its own?
As Phillip mentions in the comments, deconstruct()
is the official way to handle custom fields in django migrations.
To go on to complete the request for clarification... It would appear that there are already a couple of examples of code out there written to handle both. For example, this excerpt (to handle the on
parameter for ExclusiveBooleanField
) is taken from django-exclusivebooleanfield:
from django.db import models, transaction from django.db.models import Q from six import string_types from six.moves import reduce try: transaction_context = transaction.atomic except AttributeError: transaction_context = transaction.commit_on_success class ExclusiveBooleanField(models.BooleanField): """ Usage: class MyModel(models.Model): the_one = ExclusiveBooleanField() class MyModel(models.Model): field_1 = ForeignKey() field_2 = CharField() the_one = ExclusiveBooleanField(on=('field_1', 'field_2')) # `on` is a bit like a unique constraint, value of field # is only exclusive for rows with same value of the on fields """ def __init__(self, on=None, *args, **kwargs): if isinstance(on, string_types): on = (on, ) self._on_fields = on or () super(ExclusiveBooleanField, self).__init__(*args, **kwargs) def contribute_to_class(self, cls, name): super(ExclusiveBooleanField, self).contribute_to_class(cls, name) models.signals.class_prepared.connect(self._replace_save, sender=cls) def deconstruct(self): """ to support Django 1.7 migrations, see also the add_introspection_rules section at bottom of this file for South + earlier Django versions """ name, path, args, kwargs = super( ExclusiveBooleanField, self).deconstruct() if self._on_fields: kwargs['on'] = self._on_fields return name, path, args, kwargs def _replace_save(self, sender, **kwargs): old_save = sender.save field_name = self.name on_fields = self._on_fields def new_save(self, *args, **kwargs): def reducer(left, right): return left & Q(**{right: getattr(self, right)}) with transaction_context(): if getattr(self, field_name) is True: f_args = reduce(reducer, on_fields, Q()) u_args = {field_name: False} sender._default_manager.filter(f_args).update(**u_args) old_save(self, *args, **kwargs) new_save.alters_data = True sender.save = new_save try: from south.modelsinspector import add_introspection_rules add_introspection_rules( rules=[ ( (ExclusiveBooleanField,), [], {"on": ["_on_fields", {"default": tuple()}]}, ) ], patterns=[ 'exclusivebooleanfield\.fields\.ExclusiveBooleanField', ] ) except ImportError: pass
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With