Django: обновлять данные на веб-странице после обновления в SQLite - PullRequest
0 голосов
/ 14 марта 2019

Я готовлю веб-приложение для панели мониторинга (в Django 2.1.7), которое должно отслеживать состояние различных процессов.

Для этого я создал класс ReportEntry в models.py

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"

Это веб-приложение работает правильно.

Теперь я хотел бы вставить новую запись в базу данных SQLite (предположим, я хотел бы обновить состояние процесса), используя скрипт Python ниже

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, я пытаюсь обновить веб-страницу с помощью панели инструментов, но содержимое не обновляется. Единственное, что работает для меня, это перезапуск сервера, который не является способом перезагрузки данных.

Существует ли "простой" способ периодической перезагрузки данных из базы данных без использования redis / сельдерея и подобных приложений?

Ответы [ 2 ]

1 голос
/ 14 марта 2019

Данные не обновляются из-за этих двух строк:

    queryset = [ReportEntry.objects.filter(**k).latest('received') for k in processes]
    refresh = [a.refresh() for a in ReportEntry.objects.all()]

Каждый из них оценивает один раз, когда код вашего представления анализируется. Это происходит потому, что вы конвертируете наборы запросов в списки. Я точно не знаю, как работает ваше поле refresh, потому что вы не предоставили никакого кода, который его использует, но для queryset есть как минимум два возможных решения.

Первым решением будет переписать ваш набор запросов, так что это будет все еще набор запросов, а не список. Django знает, как обрабатывать наборы запросов в представлениях, чтобы они вели себя «лениво» (оценивать каждое представление вместо одного раза), но он не может сделать это со списками. Ваш новый набор запросов может выглядеть так:

    queryset = ReportEntry.objects.filter(**k).order_by('received').distinct('process')

Обратите внимание, что отличие от полей не работает на каждом сервере базы данных.

Второе решение - переместить ваш набор запросов в метод get_queryset:

    def get_queryset(self, *args, **kwargs):
        return [ReportEntry.objects.filter(**k).latest('received') for k in processes]
1 голос
/ 14 марта 2019

Проблема в том, что вы явно делаете запрос на уровне класса, здесь:

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]
...