Opened 6 years ago

Closed 6 years ago

#19631 closed Bug (invalid)

get_user_model() can't be used as User post_save signal sender

Reported by: Filip Wasilewski <en@…> Owned by: nobody
Component: Database layer (models, ORM) Version: 1.5-beta-1
Severity: Normal Keywords: custom user model signal
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


Or in other words there is no safe way to register a signal handler for user model (which may be customized) in a reusable app.

As the documentation says it is only possible to register a concrete user model class as a signal sender (in particular for the post_save signal).

Another limitation of custom User models is that you can't use django.contrib.auth.get_user_model() as the sender or target of a signal handler. Instead, you must register the handler with the resulting User model. See Signals for more information on registering an sending signals.

On the other hand the docs recommends another popular strategy of extending user model by one-to-one profile models that can be created/updated via post_save signal when the related user model is saved.

This is all fine and I think I understand the limitations of get_user_model(), but the things begin to break when reusable apps that make use of one-to-one user profiles are put into the context.

IMHO reusable apps should be able to work with any standard/custom model and be able to register signal handlers (in or any other safe place) on the resulting user model without having to hardcode imports of concrete model classes.

If it is is too hard to provide a decent solution for the problem I think it would be worth to document the preferred workaround/migration approach or even indicate this case as backward-incompatible change (note that Django 1.4 is going to have get_user_model() backported for compatibility reasons) for reusable apps that rely on the User's post_save signal and which try to be compatible with Django 1.4 and 1.5.

Change History (1)

comment:1 Changed 6 years ago by Anssi Kääriäinen

Resolution: invalid
Status: newclosed

According to my tests you can do this:

def foo(*args, **kwargs):
    print("foo called")
post_save.connect(foo, sender=get_user_model())

And the foo() will get called.

I think you can't use get_user_model (without the call in there), but I don't see why you would even want to do this. It is not like the user model is supposed to change after project initialization. A testing limitation this might be, but for real world use there is not limitation here.

Note: See TracTickets for help on using tickets.
Back to Top