1

I create simple Django app. Inside this app I have single checkbox. I save this checkbox state to database if it's checked in database I have True value if checkbox is uncecked I have False value. There is no problem with this part. Now I created function that prints for me every 10 second all the time this checkbox state value from database.

Function I put into views.py file and it looks like:

def get_value():
    while True:
        value_change = TurnOnOff.objects.first()
        if value_change.turnOnOff:
            print("true")
        else:
            print("false")
        time.sleep(10)

The point is that function should work all the time. For example If I in models.py code checkbox = models.BooleanField(default=False) after I run command python manage.py runserver it should give me output like:

Performing system checks...

System check identified no issues (0 silenced).
January 04, 2019 - 09:19:47
Django version 2.1.3, using settings 'CMS.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
true
true
true
true

then if I visit website and change state is should print false this is obvious. But as you notice problem is how start this method. It should work all the time even if I don't visit the website yet. And this part confuse me. How to do this properly ?

I need to admit that I tried some solutions

  • put this function at the end of manage.py file,

  • put this function into def ready(self),

  • create middleware class and put method here (example code below).

But this solutions doesn't work.

middleware class :

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        get_value()
exhuma
  • 20,071
  • 12
  • 90
  • 123
KyluAce
  • 933
  • 1
  • 8
  • 25
  • You can run a peroidic task in task queue like celery there you can put your function. check this http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html – Yugandhar Chaudhari Jan 04 '19 at 09:09

2 Answers2

3

You can achieve this by using the AppConfig.ready() hook and combining it with a sub-process/thread.

Here is an example apps.py file (based on the tutorial Polls app):

import time
from multiprocessing import Process

from django.apps import AppConfig
from django import db



class TurnOnOffMonitor(Process):
    def __init__(self):
        super().__init__()
        self.daemon = True

    def run(self):
        # This import needs to be delayed. It needs to happen after apps are
        # loaded so we put it into the method here (it won't work as top-level
        # import)
        from .models import TurnOnOff

        # Because this is a subprocess, we must ensure that we get new
        # connections dedicated to this process to avoid interfering with the
        # main connections. Closing any existing connection *should* ensure
        # this.
        db.connections.close_all()

        # We can do an endless loop here because we flagged the process as
        # being a "daemon". This ensures it will exit when the parent exists
        while True:
            value_change = TurnOnOff.objects.first()
            if value_change.turnOnOff:
                print("true")
            else:
                print("false")
            time.sleep(10)


class PollsConfig(AppConfig):
    name = 'polls'
    def ready(self):
        monitor = TurnOnOffMonitor()
        monitor.start()
exhuma
  • 20,071
  • 12
  • 90
  • 123
-1

Celery is the thing that best suits your needs from what you've described.

Celery is an asynchronous task queue/job queue based on distributed message passing. It is focused on real-time operation, but supports scheduling as well.

The execution units, called tasks, are executed concurrently on a single or more worker servers using multiprocessing, Eventlet, or gevent. Tasks can execute asynchronously (in the background) or synchronously (wait until ready).

You need to create task, run it periodically, call if you want to manually trigger is (in some view/controller).

NOTE: do not use time.sleep(10)

Community
  • 1
  • 1
vishes_shell
  • 22,409
  • 6
  • 71
  • 81
  • @KyluAce https://stackoverflow.com/questions/5439650/how-to-run-arbitrary-code-after-django-is-fully-loaded you just call your task when your django app is started. – vishes_shell Jan 04 '19 at 09:31
  • as I wrote in questinon method `ready()` doesn't work. But anyway I create this celler task using this tutorial http://docs.celeryproject.org/en/latest/django/first-steps-with-django.html put this to startup in __init__.py file and this doesn't work. I gives me `AppRegistryNotReady: Apps aren't loaded yet.` error like in previous solutions – KyluAce Jan 04 '19 at 09:43