Пользовательский менеджер не всегда добавляет вычисляемое поле для отношений «многие к одному» - PullRequest
1 голос
/ 20 марта 2019

Я использую Django 2.1 для проекта.Один из моих Models (называемый Event в приведенном ниже примере) имеет отношение «многие к одному» с другим Model (Thing в приведенном ниже примере).Первая модель должна иметь то, что я считаю вычисляемым полем.

Для иллюстрации:

class Thing(models.Model):
    ...

class Event(models.Model):
    ...
    thing = models.ForeignKey(Thing, on_delete=models.CASCADE)
    ts = models.DateTimeField(default=django.utils.timezone.now)
    _delta = timedelta()
    ...
    objects = EventManager()

    @property
    def delta(self):
        return self._delta

    @delta.setter
    def delta(self, value):
        self._delta = value

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

Поэтому у меня есть собственный менеджер для Event 's

class EventManager(models.Manager):

    def get_queryset(self):
        qs = super().get_queryset()
        for r in qs:
            r.delta = django.utils.timezone.now() - r.ts  # fake calculation
    return qs

Когда ятеперь «используйте» это, например, в шаблоне

{% for event in thing.event_set.all|dictsortreversed:"ts" %}

или в коде, подобном этому

events = thing.event_set.all()

Тогда event.delta или events.delta не задано.Даже если кажется (я не знаю, как это доказать), что используется / вызывается пользовательский менеджер (EventManager).

Я не уверен, что проблема в том, что яне может изменить набор запросов (то есть, строка с # fake calculation является проблемой) или, если это связано со следующим утверждением в Документация базовых менеджеров

Базовые менеджеры aren 't используется при запросах к связанным моделям.

или что-то совершенно другое.

Любые указатели высоко ценятся.

1 Ответ

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

В большинстве случаев набор запросов, возвращаемый менеджером (здесь: EventManager), используется не как список экземпляров, а как определение запроса . Единственное исключение - при звонке Event.objects.all(). Это единственный случай, когда ваши r объекты фактически используются. В любом другом случае добавление к ним поля delta - пустая трата времени, поскольку они вообще никогда не используются.

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

class Event(models.Model):
    def delta(self):
        return django.utils.timezone.now() - self.t

Вы можете использовать этот метод также для сортировки в шаблоне.

Альтернативой может быть добавление любых вычисляемых полей, которые вам нужны в вашем представлении (но опять же, вам нужно будет позаботиться о том, чтобы наборы запросов не изменялись при обращении к шаблону, в противном случае выдается новый запрос, объекты будут быть восстановленным и все поля, добавленные в представление, будут потеряны.

...