Search code examples
pythondjangomonkeypatchingdjango-signals

Where in Django code put code disconnecting signal and doing monkey-patching?


I'm working on custom authorization backend for Django 2.2. I don't want django to update last_login for user so I wanted to disconnect signal user_logged_in from triggering update_last_login.

I also have to do monkey patch in SimpleJWT library changing User to point OtherUserModel

Where is the best place to put this code? For now, I have added in CoreConfig.ready method and it works but is it a good place for this logic?

from django.apps import AppConfig


class CoreConfig(AppConfig):
    name = 'core'

    def ready(self):
        from django.contrib.auth import user_logged_in
        from django.contrib.auth.models import update_last_login
        user_logged_in.disconnect(update_last_login, dispatch_uid='update_last_login')

        import rest_framework_simplejwt.state
        rest_framework_simplejwt.state.User = OtherUserModel

Solution

  • I would say yes, but I think there is no clear right or wrong here, with regards to connecting signals, the Django docs state the following:

    Strictly speaking, signal handling and registration code can live anywhere you like, although it’s recommended to avoid the application’s root module and its models module to minimize side-effects of importing code.

    In practice, signal handlers are usually defined in a signals submodule of the application they relate to. Signal receivers are connected in the ready() method of your application configuration class. If you’re using the receiver() decorator, simply import the signals submodule inside ready().

    My opinion is that if the recommended way to connect signals is to do it in the ready() method of your AppConfig, disconnecting signals and related monkeypatching should also be done in this method.

    What I always do is the following:

    1. Is there any other way to solve this besides messing with the default signals/classes?
    2. If not, perform this code in the AppConfig ready() method
    3. Write some sort of unit tests or integration tests to ensure that my code does what I want it to do, even when updating dependencies etc.