Ich verwende Django 1.7-Migrationen und möchte insbesondere eine neu erstellte Datenbank mit Anfangsdaten füllen. Daher verwende ich hierfür eine Datenmigration. Es sieht wie folgt aus:Wie kann ich Signale von Django-Migrationen senden?
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),
]
Zur gleichen Zeit habe ich eine Instanz des UserDetails
Modell für jeden neuen Benutzer haben wollen:
@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)
Aber: Dieses Signal funktioniert nur außerhalb der Migration . Der Grund ist, dass apps.get_model("auth", "User")
sich von django.contrib.auth.models.User
unterscheidet, dass kein Signal gesendet wird. Wenn ich versuche, es manuell zu tun, wie diese, versagt es:
signals.post_save.send(django.contrib.auth.models.User, instance=julia, created=True)
Dies schlägt fehl, da dann versucht der Signal-Handler ein neueUserDetails
zeigt mit O2O zu einem historischenUser
zu erstellen:
ValueError: Cannot assign "<User: User object>": "UserDetails.user" must be a "User" instance.
Bummer.
Okay, ich könnte den Signal-Handler direkt aufrufen. Aber ich musste die historische Klasse in einem Schlüsselwortargument (und anderen historischen Klassen, die es benötigt) übergeben. Außerdem ist die App mit der nicht die mit dieser Datenmigration, so dass dies eine hässliche Abhängigkeit wäre, die leicht brechen kann, z. wenn die App aus INSTALLED_APPS
entfernt wird.
Also, ist das einfach eine Strombegrenzung, die ich mit hässlichem Code und einem FixMe-Kommentar ansprechen muss? Oder gibt es eine Möglichkeit, Signale aus Datenmigrationen zu senden?
Haben Sie eine Abhilfe gefunden? –
Ja, mit signal.post_migrate, weil * dies * aufgerufen wird. Aber es braucht immer noch Code, der nicht notwendig sein sollte. –
Sie sollten die Antwort posten und Ihre eigene Antwort akzeptieren, da diese Frage an der Spitze der unbeantworteten Django-Fragen steht. – dotcomly