Как я могу иметь внешний скрипт, который отслеживает изменения в базе данных?
Я использую 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