Django: связывание свойства, которое возвращает QuerySet, с аннотацией SubQuery - PullRequest
0 голосов
/ 10 февраля 2020

Я не уверен, как лучше go об этом. У меня есть следующий метод @property на моем модале:

@property
def check_ins(self):
    return SurfCheckIn.objects.filter(surf_waiver=self)

Однако я хотел бы вернуть это свойство compited в моем values() набора запросов. Я думал об использовании аннотации SubQuery:

queryset = self.get_queryset().filter(
    performance_datetime__year=date.year,
    performance_datetime__month=date.month,
    performance_datetime__day=date.day,
    void_type='0'
).exclude(
    surf_code='SPECTATOR'
).order_by(
    'performance_datetime'
).annotate(
    surf_check_ins=SubQuery()
).values()

Но я не уверен, где взять SubQuery отсюда? Каков наиболее разумный подход для извлечения этого @property внутри аннотации?

1 Ответ

1 голос
/ 11 февраля 2020

Я думаю, что @RossRogers на правильном пути. Использование prefetch_related похоже, что здесь будет работать лучше, чем аннотация, так как вы хотите вернуть все связанные объекты, а не какую-либо проверку совокупности или существования.

Чтобы использовать это, вы должны сделать prefetch_related и обновите свойство, чтобы оно возвращало значение из обратного отношения вместо выполнения нового запроса:

@property
def check_ins(self):
    # Use reverse relation here. This is the default name based on your model,
    # but if the foreign key has a `related_name` set, use that value instead.
    return self.surfcheckin_set.all()

Вместо аннотации вы должны были бы предварительно выбрать набор, и это предотвратит попадание в базу данных на каждый возвращенный отказ :

# Again, replace surcheckin_set with the `related_name` if set on the foreign key for `surf_waiver`.
queryset = self.get_queryset().filter(
    performance_datetime__year=date.year,
    performance_datetime__month=date.month,
    performance_datetime__day=date.day,
    void_type='0'
).exclude(
    surf_code='SPECTATOR'
).prefetch_related(
    "surfcheckin_set"
).order_by(
    'performance_datetime'
).values()

Вызов prefetch_related здесь означает, что вы выполните один запрос для всего набора запросов и передадите значения обратно менеджеру для обратной связи. Когда свойство вызывает .all() для обратного отношения, оно будет использовать этот результат кэшированного запроса.

...