2015-04-10 15 views
22

Torna nei giorni delle migrazioni del Sud, se si voleva creare un campo modello personalizzato che ha esteso le funzionalità di un campo Django, si potrebbe dire del Sud per utilizzare le regole di introspezione della classe genitore in questo modo:Esiste una sostituzione di Django 1.7+ per l'add_introspection_rules() di South?

from south.modelsinspector import add_introspection_rules 
add_introspection_rules([], ["^myapp\.stuff\.fields\.SomeNewField"]) 

Ora che le migrazioni sono state spostate a Django, esiste un equivalente non sud di quanto sopra? È ancora più necessario un equivalente, o la nuova roba di migrazione è abbastanza intelligente da essere in grado di capirlo da sola?

+0

mai trovare una risposta a questo? –

+3

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

+2

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

risposta

6

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 
+0

@mlissner: Penso che questo copra i riferimenti esterni formali e l'esempio che hai richiesto. –

+0

Custom ** deconstruct() ** metodo ** senza l'utilizzo di super ** - http://stackoverflow.com/questions/31953802/upgrading-from-django-1-6-to-1-7-getting-callable -is-non-serializzare-quando-running –

Problemi correlati