简体   繁体   English

如何拥有一个跟踪数据库更改的外部脚本?

[英]How can I have an external script that tracks changes in database?

I am using Django and have a skeleton website with a single button that increments an IntegerField in my database.我正在使用 Django 并且有一个带有单个按钮的骨架网站,该按钮在我的数据库中递增 IntegerField。 I want to have an external script which continually reads this IntegerField and reports when a change has been made.我想要一个外部脚本,它不断地读取这个 IntegerField 并在发生更改时报告。

models.py模型.py

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

views.py视图.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')

I thought I could simply achieve this inside the view function but I've had difficulty detecting a change because the pre & post values above are the same when I print them even though post is clearly created after the field is incremented.我想我可以简单地在视图 function 中实现这一点,但我很难检测到变化,因为当我打印它们时,上面的 pre 和 post 值是相同的,即使 post 是在字段增加后明确创建的。

I have a watcher.py file inside my app directory where I am trying to program a script that would run in the background and report changes to the database.我的应用程序目录中有一个 watcher.py 文件,我试图在其中编写一个脚本,该脚本将在后台运行并报告对数据库的更改。 Here's what I have so far:这是我到目前为止所拥有的:

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()

When I try to run this, I get the error: Model class models.Counter doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS .当我尝试运行它时,我收到错误: Model class models.Counter 没有声明明确的 app_label 并且不在 INSTALLED_APPS 的应用程序中 I don't understand why this comes up and I don't know how to resolve it;我不明白为什么会出现这种情况,也不知道如何解决; I don't think making Counter it's own app is suitable.我不认为让 Counter 成为自己的应用程序是合适的。

I am very lost at this point so any help is appreciated.在这一点上我非常迷茫,所以任何帮助表示赞赏。 Am I going about this the right way?我会以正确的方式解决这个问题吗? Is there an easier way to do this?有没有更简单的方法来做到这一点?

You must run this script in a django app.您必须在 django 应用程序中运行此脚本。 This could be done in different manner, but a way more simple one would be to use the before/post save signal of Django, so you know when this field is modified: https://docs.djangoproject.com/en/4.1/ref/signals/#django.db.models.signals.post_save这可以以不同的方式完成,但更简单的方法是使用 Django 的前/后保存信号,因此您知道何时修改此字段: https://docs.djangoproject.com/en/4.1/参考/信号/#django.db.models.signals.post_save

If you still want to use a dedicated runner, you can create a thread/process that run aside Django.如果您仍想使用专用运行器,您可以创建一个在 Django 旁边运行的线程/进程。 Still you have one issue in your code,您的代码中仍然存在一个问题,

post = ctr.count

This will not reload the object state from the database.这不会从数据库重新加载 object state。 You need to reload the object manually to ensure it is uptodate.您需要手动重新加载 object 以确保它是最新的。 Other way you would not detect any changes:其他方式您不会检测到任何更改:

ctr.refresh_from_db()
post = ctr.count

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM