Search code examples
pythondjangoserverneural-network

Django: Execute code only for `manage.py runserver`, not for `migrate`, `help` etc


We are using Django as backend for a website that provides various things, among others using a Neural Network using Tensorflow to answer to certain requests.

For that, we created an AppConfig and added loading of this app config to the INSTALLED_APPS in Django's settings.py. This AppConfig then loads the Neural Network as soon as it is initialized:

settings.py:

INSTALLED_APPS = [
...
    'bert_app.apps.BertAppConfig',
]

.../bert_apps/app.py:

class BertAppConfig(AppConfig):
    name = 'bert_app'
    if 'bert_app.apps.BertAppConfig' in settings.INSTALLED_APPS:
        predictor = BertPredictor() #loads the ANN.

Now while that works and does what it should, the ANN is now loaded for every single command run through manage.py. While we of course want it to be executed if you call manage.py runserver, we don't want it to be run for manage.py migrate, or manage.py help and all other commands.

I am generally not sure if this is the proper way how to load an ANN for a Django-Backend in general, so does anybody have any tips how to do this properly? I can imagine that loading the model on startup is not quite best practice, and I am very open to suggestions on how to do that properly instead.

However, there is also some other code besides the actual model-loading that also takes a few seconds and that is definitely supposed to be executed as soon as the server starts up (so on manage.py runserver), but also not on manage.py help (as it takes a few seconds as well), so is there some quick fix for how to tell Django to execute it only on runserver and not for its other commands?


Solution

  • I had a similar problem, solved it with checking argv.

    class SomeAppConfig(AppConfig):
    
        def ready(self, *args, **kwargs):
            is_manage_py = any(arg.casefold().endswith("manage.py") for arg in sys.argv)
            is_runserver = any(arg.casefold() == "runserver" for arg in sys.argv)
    
            if (is_manage_py and is_runserver) or (not is_manage_py):
                init_your_thing_here()
    

    Now a bit closer to the if not is_manage_py part: in production you run your web server with uwsgi/uvicorn/..., which is still a web server, except it's not run with manage.py. Most likely, it's the only thing that you will ever run without manage.py


    Use AppConfig.ready() - it's intended for it:

    Subclasses can override this method to perform initialization tasks such as registering signals. It is called as soon as the registry is fully populated. - [django documentation]

    To get your AppConfig back, use:

    from django.apps import apps
    apps.get_app_config(app_name)
    # apps.get_app_configs()  # all