Сохранение результатов менеджера моделей django в базе данных - PullRequest
0 голосов
/ 15 ноября 2011

Я хочу представить общую статистику об экземплярах класса "ModelClass" на веб-странице для моих пользователей.Допустим, есть несколько тысяч ModelClass-объектов и есть много статистики, которую мне нужно вычислить.Я понял, что могу сделать это с менеджерами моделей, и вот (очень) упрощенный пример:

class ModelClassCustomManager(models.Manager):
    def get_query_set(self):
        return super(ModelClassCustomManager, self).get_query_set().filter(is_complete = True)


class ModelClass(models.Model):
    is_complete = models.BooleanField(default = False)
    ...
    objects = models.Manager()
    complete_objects = ModelClassCustomManager()

Меня беспокоит то, что это истощает много ресурсов, если это вычисляется, когда пользователи просматриваютстр.Поэтому я хотел бы рассчитать его только тогда, когда я изменяю или создаю новые объекты ModelClass, поскольку это единственный раз, когда статистика действительно изменяется.Я думаю, это можно сделать, переопределив метод ModelClass save ().

Каков наилучший способ сохранить эти результаты?Должен ли я создать другую django-модель для хранения вычисленной статистики или есть другой способ хранения этой информации?

РЕДАКТИРОВАТЬ: Спасибо пастилегам за хороший ответ.Однако при таком способе возникают незначительные ошибки, и я решил объяснить их здесь, на случай, если кто-нибудь еще столкнется с этой проблемой.

Прежде всего, я неправильно поместил импорт в ModelClass вверху, поэтому получил круговую зависимость, которая дала странные результаты.Чтобы избавить себя от разочарований, поместите их так, как это делали пастилеги.Во-вторых, чтобы перезаписать предыдущие расчеты статистики (а не создавать новые каждый раз), просто замените

if sender is ModelClass and instance is not Null:
    count = ModelClass.objects.all().count()
    stat = Stat(name='some_name', value=count).save()

следующим:

if sender is ModelClass:
    count = Match.objects.all().count()
    try:
        stat = Stat.objects.get(key="Total")
        stat.update(key="Total", value=count) #Update statistic
    except: 
        Stat(key="Total", value=count).save() #Create new

1 Ответ

4 голосов
/ 15 ноября 2011

Я бы создал приложение под названием статистика (или подобное), которое имеет простую модель для хранения ключей, пар значений:

class Stat(models.Model):
    key = models.CharField(..)
    value = models.CharField(...)

, а затем использовал бы сигнал в вашей собственной модели для запуска функции каждый разпользователь сохраняет / обновляет экземпляр вашей модели.В models.py :

class ModelClass(models.Model):
    ...

from django.db.models.signals import post_save
from myapp.signal import updates_stats
post_save.connect(updates_stats, sender=ModelClass)

и затем создайте функцию приемника, чтобы вычислять статистику, которая вам когда-либо понадобится в signal.py

from myapp.models import ModelClass
from stats.models import Stat
def update_stats(sender, instance, signal, *args, **kwargs):
    if sender is ModelClass and instance is not Null:
        count = ModelClass.objects.all().count()
        stat = Stat(name='some_name', value=count).save()

Это очень простой и базовый подход, в котором только излагается, как вы можете использовать сигналы для выполнения расчетов, но это хорошее начало.В идеале вы должны попытаться вычислить эти значения вне цикла запрос / ответ (особенно, если они представляют собой большие вычисления), так как это приведет к зависанию вашего сервера и, возможно, к истечению времени ожидания ваших запросов, поэтому вам следует рассмотреть возможность использования системы очередей / задач, такой как Celery, для выполнениярасчет в фоновом режиме

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...