Come Phillip menziona nei commenti, deconstruct()
è il official way to handle custom fields nelle migrazioni Django.
Per continuare a completare la richiesta di chiarimenti ... Sembrerebbe che ci siano già un paio di esempi di codice scritti per gestire entrambi. Ad esempio, questo estratto (per gestire il parametro on
per ExclusiveBooleanField
) è tratto da 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
mai trovare una risposta a questo? –
Quando ho eseguito l'aggiornamento a Django 1.7, ho rimosso la chiamata a 'add_introspection_rules()' e le cose sembrano "funzionano", almeno per i campi personalizzati che stiamo usando. Potrebbero esserci ancora casi in cui è necessario un equivalente di 'add_introspection_rules()', ma non ho trovato un equivalente, e non ho mai incontrato scenari specifici, tuttavia, che * necessitano * di un equivalente. – Troy
Anche in questo problema. Sembra che l'override di 'deconstruct()' ti consenta di superare la maggior parte dei problemi, ma sto riscontrando un problema con Django che non è in grado di serializzare funzioni non di primo livello. – dursk