Django:在 SQLite 中更新后刷新网页上的数据
Django: Refresh data on webpage after update in SQLite
我正在准备一个仪表板 Web 应用程序(在 Django 2.1.7 中),它应该监视不同进程的状态。
为此,我在 models.py
中创建了一个 class ReportEntry
class ReportEntry(models.Model):
process = models.CharField(max_length=30)
received = models.DateTimeField(auto_now_add=True)
status = models.SmallIntegerField(default=1)
def refresh(self):
self.refresh_from_db()
self.save()
要查看仪表板,我正在使用 django-tables2。 view.py 脚本包含
from .tables import SimpleTable
from django_tables2 import SingleTableView
from .models import ReportEntry
class TableView(SingleTableView):
table_class = SimpleTable
processes = ReportEntry.objects.values('process').distinct()
queryset = [ReportEntry.objects.filter(**k).latest('received') for k in processes]
refresh = [a.refresh() for a in ReportEntry.objects.all()]
template_name = "simple_list.html"
此 Web 应用程序工作正常。
现在,我想使用下面的 Python 脚本向 SQLite 数据库插入一个新条目(假设我想更新进程的状态)
from sqlite3 import connect
def create_connection(db_file):
try:
conn = connect(db_file)
return conn
except Exception as e:
print(e)
return None
if __name__ == '__main__':
from datetime import datetime, timedelta
database = r'C:\Apps\Python3702\my_venv\web\mysite\db.sqlite3'
conn = create_connection(database)
cur = conn.cursor()
sql = '''INSERT INTO main.monitor_reportentry(process,received,status)
VALUES(?,?,?)'''
cur.execute(sql, ['test', datetime.now(), 1])
conn.commit()
conn.close()
当我执行脚本并将数据插入 SQLite 数据库时,我尝试用我的仪表板刷新网页,但内容没有更新。唯一对我有用的是重新启动服务器,这不是重新加载数据的方法。
是否有 "easy" 方法可以在不使用 redis/celery 和类似应用程序的情况下以某种方式定期从数据库重新加载数据?
问题是您在 class 级别显式执行查询,此处:
queryset = [ReportEntry.objects.filter(**k).latest('received') for k in processes]
尽管有名称,但您在这里并不是定义一个查询集——这将是惰性的,并根据需要进行更新——而是一个具体的项目列表,每个进程只评估一次。不要这样做。
相反,定义 get_queryset()
方法:
class TableView(SingleTableView):
table_class = SimpleTable
template_name = "simple_list.html"
def get_queryset(self, *args, **kwargs):
processes = ReportEntry.objects.values('process').distinct()
return [ReportEntry.objects.filter(**k).latest('received') for k in processes]
由于这两行,数据没有刷新:
queryset = [ReportEntry.objects.filter(**k).latest('received') for k in processes]
refresh = [a.refresh() for a in ReportEntry.objects.all()]
当您的视图代码被解析时,它们中的每一个都会计算一次。发生这种情况是因为您正在将查询集转换为列表。我不完全知道你的 refresh
字段是如何工作的,因为你没有提供任何使用它的代码,但是对于 queryset
至少有两种可能的解决方案。
第一个解决方案是重写您的查询集,因此它仍然是查询集,而不是列表。 Django 知道如何处理视图中的查询集,因此它们的行为是 "lazy"(在每个视图上计算而不是一次),但它不能对列表执行此操作。您的新查询集可能如下所示:
queryset = ReportEntry.objects.filter(**k).order_by('received').distinct('process')
请注意,distinct with fields 并不适用于所有数据库后端。
第二种解决方案是将查询集移动到 get_queryset
方法:
def get_queryset(self, *args, **kwargs):
return [ReportEntry.objects.filter(**k).latest('received') for k in processes]
我正在准备一个仪表板 Web 应用程序(在 Django 2.1.7 中),它应该监视不同进程的状态。
为此,我在 models.py
中创建了一个 class ReportEntryclass ReportEntry(models.Model):
process = models.CharField(max_length=30)
received = models.DateTimeField(auto_now_add=True)
status = models.SmallIntegerField(default=1)
def refresh(self):
self.refresh_from_db()
self.save()
要查看仪表板,我正在使用 django-tables2。 view.py 脚本包含
from .tables import SimpleTable
from django_tables2 import SingleTableView
from .models import ReportEntry
class TableView(SingleTableView):
table_class = SimpleTable
processes = ReportEntry.objects.values('process').distinct()
queryset = [ReportEntry.objects.filter(**k).latest('received') for k in processes]
refresh = [a.refresh() for a in ReportEntry.objects.all()]
template_name = "simple_list.html"
此 Web 应用程序工作正常。
现在,我想使用下面的 Python 脚本向 SQLite 数据库插入一个新条目(假设我想更新进程的状态)
from sqlite3 import connect
def create_connection(db_file):
try:
conn = connect(db_file)
return conn
except Exception as e:
print(e)
return None
if __name__ == '__main__':
from datetime import datetime, timedelta
database = r'C:\Apps\Python3702\my_venv\web\mysite\db.sqlite3'
conn = create_connection(database)
cur = conn.cursor()
sql = '''INSERT INTO main.monitor_reportentry(process,received,status)
VALUES(?,?,?)'''
cur.execute(sql, ['test', datetime.now(), 1])
conn.commit()
conn.close()
当我执行脚本并将数据插入 SQLite 数据库时,我尝试用我的仪表板刷新网页,但内容没有更新。唯一对我有用的是重新启动服务器,这不是重新加载数据的方法。
是否有 "easy" 方法可以在不使用 redis/celery 和类似应用程序的情况下以某种方式定期从数据库重新加载数据?
问题是您在 class 级别显式执行查询,此处:
queryset = [ReportEntry.objects.filter(**k).latest('received') for k in processes]
尽管有名称,但您在这里并不是定义一个查询集——这将是惰性的,并根据需要进行更新——而是一个具体的项目列表,每个进程只评估一次。不要这样做。
相反,定义 get_queryset()
方法:
class TableView(SingleTableView):
table_class = SimpleTable
template_name = "simple_list.html"
def get_queryset(self, *args, **kwargs):
processes = ReportEntry.objects.values('process').distinct()
return [ReportEntry.objects.filter(**k).latest('received') for k in processes]
由于这两行,数据没有刷新:
queryset = [ReportEntry.objects.filter(**k).latest('received') for k in processes]
refresh = [a.refresh() for a in ReportEntry.objects.all()]
当您的视图代码被解析时,它们中的每一个都会计算一次。发生这种情况是因为您正在将查询集转换为列表。我不完全知道你的 refresh
字段是如何工作的,因为你没有提供任何使用它的代码,但是对于 queryset
至少有两种可能的解决方案。
第一个解决方案是重写您的查询集,因此它仍然是查询集,而不是列表。 Django 知道如何处理视图中的查询集,因此它们的行为是 "lazy"(在每个视图上计算而不是一次),但它不能对列表执行此操作。您的新查询集可能如下所示:
queryset = ReportEntry.objects.filter(**k).order_by('received').distinct('process')
请注意,distinct with fields 并不适用于所有数据库后端。
第二种解决方案是将查询集移动到 get_queryset
方法:
def get_queryset(self, *args, **kwargs):
return [ReportEntry.objects.filter(**k).latest('received') for k in processes]