Signals with MigratorTestCase

Hi,

I created a Profile model with a one-to-one relation to the default User model and added two receiver functions for User’s post_save signal for creating and editing so that a profile is created or saved (as shown in https://simpleisbetterthancomplex.com/tutorial/2016/07/28/how-to-create-django-signals.html).
I added a migration to create missing profiles and want to test it with django-test-migrations (https://pypi.org/project/django-test-migrations/).

From quite some trial and error I conclude that signals are disabled for MigratorTestCase. Is that really so? How is this done? Can they be enabled generally without replicating the receiver functions from the model?

Is it okay to use asserts within the prepare function of the MigratorTestCase?

As a side note, I originally tried to create the missing profiles in the migration via user.profile = Profile() as I thought the one-to-one relationship would allow this but changed it to Profile(user=user) to make it work. Can the first version be used at all?

Thanks for your help!

It seems it’s done here, for the pre and post migrate signals, by directly mutating the attributes on the signal object:

I imagine this is done to avoid repeating such post_migrate signals as the content type framework’s create_contenttypes function: https://github.com/django/django/blob/06c8565a4650b359bdfa59f9707eaa0d1dfd7223/django/contrib/contenttypes/management/init.py#L105

If this wasn’t clear I suggest making an issue / PR to that project for better documentation.

I presume so but it feels like this is a question for that project, which you could do in a GitHub issue.

I don’t believe the first version can be used.

1 Like

Thanks for your reply!

It seems it’s done here, for the pre and post migrate signals, by directly mutating the attributes on the signal object:

I saw the _pre_setup method but thought it would have no effect on post_save receivers since it’s about pre_migrate and post_migrate receivers. And it’s a list instead of a dictionary (but I don’t know yet how signals are handled internally, just assuming). :thinking:

I presume so but it feels like this is a question for that project, which you could do in a GitHub issue.

This package’s prepare method is not that different from other tests’ setup method. So it’s not a question exclusive for that project’s GitHub I think. Anyway, I will certainly ask them of their thoughts on the topic.

I don’t believe the first version can be used.

Thought so but good to have another opinion on that.

Ah, that’s the signal you’re after. I think the signal isn’t attached because you aren’t using the original model in your migration, but a temporary “historical” version of it from get_model , as per the first paragraph of the RunPython docs. If you want the signal to fire you’ll have to reattach it.

I think the signal isn’t attached because you aren’t using the original model in your migration, but a temporary “historical” version of it from get_model

I thought about that as well. But the migration I start from was created with the same change the post_saves were introduced. So I would think those should be loaded at the same time. Does get_model use the files’ timestamps?

get_model returns a brand new in-memory class with the current fields. It is unrelated to the model class in your source code, and any attached signal handlers, and only built from the executed state in your migration files.

1 Like