Как я могу иметь внешний скрипт, который отслеживает изменения в базе данных?

Я использую Django и имею скелет сайта с одной кнопкой, которая увеличивает IntegerField в моей базе данных. Я хочу иметь внешний скрипт, который постоянно считывает это IntegerField и сообщает, когда было сделано изменение.

models.py

class Counter(models.Model):
    count = models.PositiveIntegerField(default=0)

views.py

def index(request):
    ctr = Counter.objects.get(id=1)
    pre = ctr.count
    print(f"pre: {pre}")

    if request.method == 'POST':
        if request.POST.get("increment"):
            Counter.objects.filter(id=1).update(count=F('count') + 1)
            post = ctr.count
            print(f"pre: {pre}")


return render(request, 'increment.html')

Я думал, что смогу просто добиться этого внутри функции представления, но мне было трудно обнаружить изменение, потому что значения pre & post выше одинаковы, когда я печатаю их, хотя post явно создается после увеличения поля.

У меня есть файл watcher.py в каталоге app, где я пытаюсь запрограммировать скрипт, который будет работать в фоновом режиме и сообщать об изменениях в базе данных. Вот что у меня есть на данный момент:

from django.conf import settings

settings.configure(DEBUG=True)

import django
django.setup()

import models
import time
from ahelper import settings
from threading import Thread


def watcher():
    ctr = models.Counter.objects.get(id=1)
    pre = ctr.count
    print(f"{pre}")
    print("start loop")
    while (1):
        temp = time.time()
        post = ctr.count
        if pre != post:
            print("Change detected")
            response_time = (time.time() - temp) * 1000
            print(f"{response_time}ms")

t = Thread(target=watcher, daemon=True)
t.start()

Когда я пытаюсь запустить это, я получаю ошибку: Модель класса models.Counter не объявляет явную метку app_label и не находится в приложении в INSTALLED_APPS. Я не понимаю, почему это происходит, и не знаю, как это решить; я не думаю, что создание собственного приложения для счетчика подходит.

На данный момент я очень растерян, поэтому любая помощь будет принята с благодарностью. Правильно ли я поступаю? Есть ли более простой способ сделать это?

Вы должны запустить этот скрипт в приложении django. Это можно сделать разными способами, но более простым будет использование сигнала сохранения до/после сохранения в Django, чтобы вы знали, когда это поле изменено: https://docs.djangoproject.com/en/4.1/ref/signals/#django.db.models.signals.post_save

Если вы все еще хотите использовать выделенный бегунок, вы можете создать поток/процесс, который будет выполняться в стороне от Django. Тем не менее, у вас есть одна проблема в вашем коде,

post = ctr.count

При этом состояние объекта не будет перезагружено из базы данных. Вам необходимо перезагрузить объект вручную, чтобы убедиться в его актуальности. В противном случае вы не обнаружите никаких изменений:

ctr.refresh_from_db()
post = ctr.count
Вернуться на верх