I use Django 1.7 migrations, and in particular, want to populate a newly-created database with initial data. Thus, I use a data migration for this. It looks like this:
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),
]
At the same time, I want to have an instance of the UserDetails
model for every new user:
@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)
But: This signal works only outside the migration. The reason is that apps.get_model("auth", "User")
is different enough from django.contrib.auth.models.User
that no signal is sent. If I try to do it manually, like this, it fails:
signals.post_save.send(django.contrib.auth.models.User, instance=julia, created=True)
This fails because then, the signal handler tries to create a new UserDetails
pointing with O2O to a historical User
:
ValueError: Cannot assign "<User: User object>": "UserDetails.user" must be a "User" instance.
Bummer.
Okay, I could call the signal handler directly. But I had to pass the historical UserDetails
class in a keyword argument (and other historical classes that it needs). Besides, the app with the UserDetails
is not the one with this data migration, so this would be an ugly dependency which easily may break, e.g. if the UserDetails
app is removed from INSTALLED_APPS
.
So, is this simply a current limitation that I have to address with ugly code and a FixMe comment? Or is there a way to send signals out of data migrations?