Sto creando una migrazione dei dati utilizzando il metodo RunPython
. Tuttavia, quando provo a eseguire un metodo sull'oggetto nessuno è definito. È possibile chiamare un metodo definito su un modello usando RunPython
?Migrazioni di Django RunPython non è in grado di chiamare i metodi del modello
risposta
hai chiamato il tuo modello come detto nella documentazione?
def combine_names(apps, schema_editor):
# We can't import the Person model directly as it may be a newer
# version than this migration expects. We use the historical version.
Person = apps.get_model("yourappname", "Person")
for person in Person.objects.all():
person.name = "%s %s" % (person.first_name, person.last_name)
person.save()
Data-Migration Perché a questo punto, non è possibile importare il modello direttamente:
from yourappname.models import Person
Aggiornamento
Il codice interno Django è in questo file Django/db/migrazioni /state.py django.db.migrations.state.ModelState # construct_fields
def construct_fields(self):
"Deep-clone the fields using deconstruction"
for name, field in self.fields:
_, path, args, kwargs = field.deconstruct()
field_class = import_string(path)
yield name, field_class(*args, **kwargs)
C'è solo i campi che sono cloni in un "falso" istanza modello:
MyModel.__module__ = '__fake__'
metodi modello non sono disponibili nelle migrazioni, tra cui la migrazione dei dati.
Tuttavia, vi è una soluzione alternativa, che dovrebbe essere abbastanza simile ai metodi di chiamata del modello. È possibile definire funzioni all'interno di migrazioni che imitano i metodi di modello che si desidera utilizzare.
Se trovassi questo metodo:
class Order(models.Model):
'''
order model def goes here
'''
def get_foo_as_bar(self):
new_attr = 'bar: %s' % self.foo
return new_attr
È possibile scrivere funzione all'interno di script di migrazione come:
def get_foo_as_bar(obj):
new_attr = 'bar: %s' % obj.foo
return new_attr
def save_foo_as_bar(apps, schema_editor):
old_model = apps.get_model("order", "Order")
for obj in old_model.objects.all():
obj.new_bar_field = get_foo_as_bar(obj)
obj.save()
quindi utilizzarlo nelle migrazioni:
migrazioniclass Migration(migrations.Migration):
dependencies = [
('order', '0001_initial'),
]
operations = [
migrations.RunPython(save_foo_as_bar)
]
questo modo sarà lavoro. Ci sarà un po 'di ripetizione del codice, ma non importa perché si suppone che le migrazioni dei dati siano operazioni singole nel particolare stato di un'applicazione.
sì. puoi accedere ai campi su un modello ma non i metodi dei modelli metodi – user2954587
non ha funzionato per me! –