Django: связь свойства, возвращающего QuerySet, с аннотацией SubQuery

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

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

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

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

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

Всего 1 ответ


Я думаю, что @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=Ɔ'
).exclude(
    surf_code='SPECTATOR'
).prefetch_related(
    "surfcheckin_set"
).order_by(
    'performance_datetime'
).values()

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


Есть идеи?

10000