Io uso le migrazioni di Django 1.7 e, in particolare, voglio popolare un database appena creato con i dati iniziali. Pertanto, io uso una migrazione dei dati per questo. Ecco come si presenta:Come posso inviare segnali dalle migrazioni di Django?
def populate_with_initial_data(apps, schema_editor):
User = apps.get_model("auth", "User")
new_user = User.objects.create(username="nobody")
class Migration(migrations.Migration):
...
operations = [
migrations.RunPython(populate_with_initial_data),
]
Allo stesso tempo, voglio avere un'istanza del modello UserDetails
per ogni nuovo utente:
@receiver(signals.post_save, sender=django.contrib.auth.models.User)
def add_user_details(sender, instance, created, **kwargs):
if created:
my_app.UserDetails.objects.create(user=instance)
Ma: Questo segnale funziona solo al di fuori della migrazione . Il motivo è che apps.get_model("auth", "User")
è abbastanza diverso da django.contrib.auth.models.User
che nessun segnale viene inviato. Se provo a farlo manualmente, in questo modo, non riesce:
signals.post_save.send(django.contrib.auth.models.User, instance=julia, created=True)
questo viene a mancare, perché poi, il gestore di segnale tenta di creare un nuovaUserDetails
indicando con O2O ad un storicaUser
:
ValueError: Cannot assign "<User: User object>": "UserDetails.user" must be a "User" instance.
Bummer.
OK, potrei chiamare direttamente il gestore di segnale. Ma ho dovuto passare la classe storica UserDetails
in un argomento di parole chiave (e altre classi storiche di cui ha bisogno). Inoltre, l'app con il UserDetails
non è quella con questa migrazione dei dati, quindi questa sarebbe una brutta dipendenza che potrebbe facilmente rompersi, ad es. se l'app UserDetails
viene rimossa da INSTALLED_APPS
.
Quindi, si tratta semplicemente di una limitazione di corrente che devo risolvere con un brutto codice e un commento FixMe? O c'è un modo per inviare segnali dalle migrazioni dei dati?
hai trovato una soluzione alternativa per questo? –
Sì, utilizzando signal.post_migrate perché questo * è * chiamato. Ma ha ancora bisogno del codice che non dovrebbe essere necessario. –
Dovresti pubblicare la risposta e accettare la tua risposta in quanto questa domanda è in cima alle domande senza risposta di django. – dotcomly