In primo luogo, il motivo per cui è in esecuzione init 3 volte?
Anche se il models.py
viene importato solo una volta, gli Field
oggetti in esso creati, come ad esempio ...
myfield = MyMixinCharField(max_length=512, new_arg="myarg")
... sono clonati più volte, che coinvolge chiamando il costruttore campo utilizzando la parola chiave args sono stati originariamente creati con. È possibile utilizzare il modulo traceback
per vedere dove sta accadendo ...
import traceback
class MyMixin(object):
def __init__(self, new_arg=None, *args, **kwargs):
super(MyMixin, self).__init__(*args, **kwargs)
print self.__class__, new_arg
traceback.print_stack()
... che presentino i seguenti diverse volte in uscita ...
File "django/db/migrations/state.py", line 393, in from_model
fields.append((name, field.clone()))
File "django/db/models/fields/__init__.py", line 464, in clone
return self.__class__(*args, **kwargs)
File "myproj/myapp/models.py", line 11, in __init__
traceback.print_stack()
Dove si trova il kwarg 'new_arg' nel secondo due?
Quando si originariamente chiamato ...
myfield = MyMixinCharField(max_length=512, new_arg="myarg")
... "myarg"
viene passato come parametro new_arg
a ...
def __init__(self, new_arg=None, *args, **kwargs):
... ma perché don passare quel parametro al costruttore sottostante Field
...
super(MyMixin, self).__init__(*args, **kwargs)
...non è memorizzato da nessuna parte nell'oggetto sottostante Field
, quindi quando il campo è clonato, il parametro new_arg
non viene passato al costruttore.
Tuttavia, passando l'opzione per il costruttore della superclasse non funziona, perché il CharField
non supporta tale arg parola chiave, così avrai ...
File "myproj/myapp/models.py", line 29, in MyMixinModelTest
myfield = MyMixinCharField(max_length=512, new_arg="myarg")
File "myproj/myapp/models.py", line 25, in __init__
super(MyMixinCharField, self).__init__(*args, **kwargs)
File "django/db/models/fields/__init__.py", line 1072, in __init__
super(CharField, self).__init__(*args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'new_arg'
Come creo un mixin di campo per il django?
A causa di questo comportamento la clonazione, se si desidera aggiungere opzioni dei campi personalizzati, è necessario definire un metodo personalizzato deconstruct()
in modo che Django può serializzare la nuova opzione ...
class MyMixin(object):
def __init__(self, new_arg=None, *args, **kwargs):
super(MyMixin, self).__init__(*args, **kwargs)
self.new_arg = new_arg
print self.__class__, new_arg
def deconstruct(self):
name, path, args, kwargs = super(MyMixin, self).deconstruct()
kwargs['new_arg'] = self.new_arg
return name, path, args, kwargs
class MyMixinCharField(MyMixin, models.CharField):
pass
class MyMixinModelTest(models.Model):
myfield = MyMixinCharField(max_length=512, new_arg="myarg")
... quali uscite ...
<class 'myapp.models.MyMixinCharField'> myarg
<class 'myapp.models.MyMixinCharField'> myarg
<class 'myapp.models.MyMixinCharField'> myarg
Quale versione di django stai usando? – Aya
Sto usando la versione 1.9 – jmerkow
@solarissmoke, non è la stessa domanda. –