4
votes

TL;DR In my django project, where do I put my "start-a-thread" code to make a thread run as soon as the django server is up?

First of all, Happy New Year Everyone! This is a question from a newbie so it might seem dumb. Thank you for your patience and help in advance!

Background Information
Recently I am writing a MQTT forwarding program which receives MQTT message. I'd like user to set some rules to handle messages to be forwarded so I chose django to build a web server. User can edit the rules themselves on the web page.
For the MQTT client I need to have a thread to receive MQTT message no matter if the user opens a webpage or not, so I cannot write it in the view.py. If I write a shell to start django server and my script separately, I am not sure how to pass the users settings from django server to my mqtt client script.

Question
1. Is there a way to start a background thread as soon as I typed python manage.py runserver?
2. One of the user settings is the MQTT server host, so once the user change this entry on the webpage, the background MQTT client should restart and connect to the new host. Is there any ways to achieve that?

I did some research and some likely solutions I found were django-background-tasks or Celery but I am not sure those are the right way, and I think this problem is too small to import another heavy module to deal with. Please give me some advice! If you are unclear about anything feel free to ask me!
Thank you again!

1

1 Answers

6
votes

What I think you can do is to start the thread in the ready() method your AppConfig in apps.py

Here a simple example

# apps.py
from django.apps import AppConfig
from threading import Thread

class TestThread(Thread):

    def run(self):
        print('Thread running')



class StackConfig(AppConfig):
    name = 'stack'

    def ready(self):
        TestThread().start()

If you need code from other parts of your app be aware that you cannot import this on the module level, i.e. if you try something like this in your apps.py

#apps.py
from . models import Code

an exception will be raised:

django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet

In order to avoid this you need to do the import in your ready() method:

#apps.py
class StackConfig(AppConfig):
        name = 'stack'

        def ready(self):
            from stack.models import Code
            TestThread().start()

This is decribed in the docs.

In order for all this to work make sure you start your app in your settings.INSTALLED_APPS like so

'stack.apps.StackConfig',