Получить несколько моделей, связанных в одном запросе, в соответствии с некоторыми условиями в Django - PullRequest
1 голос
/ 03 августа 2020

У меня есть модель Car, которая имеет несколько ассоциаций с другими моделями через внешние ключи и многие поля, в данном случае Car имеет один Owner и много Obligations.

Отношения модели

class Car(TimeStampedModel, models.Model):
    owner = models.ForeignKey(
        to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE
    )

class Obligation(TimeStampedModel, models.Model):
    """Representation of the obligations that a car should have up to date."""
    car = models.ForeignKey(to=Car, on_delete=models.CASCADE)
    expiration_date = models.DateField(
        default=date.today,
    )

Ожидаемый результат

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

Что я пробовал

1. Получить автомобили с просроченными обязательствами

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

class CarManager(models.Manager):
    """Define a manager for Car model."""

    def with_obligations_expired(self) -> "QuerySet[Car]":
        """Returns a Car given where there is at least one Obligation that is expired."""

        return (
            self.get_queryset()
            .filter(obligation__expiration_date__lte=date.today())
            .distinct()
        )

2. Получить владельцев этих автомобилей с истекшими обязательствами

Я запускаю метод таможенного менеджера with_obligations_expired(), чтобы получить автомобили с просроченными обязательствами. Благодаря этому я могу получить доступ к владельцам и обязательствам этого транспортного средства.

cars_with_expired_obligations = Car.objects.with_obligations_expired()
owners = [car.owner for car in cars_with_expired_obligations]
obligations = # ...something similar to owners 

Проблема

С помощью приведенного выше кода я могу получить информацию о владельцах и обязательствах для этого транспортного средства с истекшими обязательствами, но отдельно.

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

1 Ответ

1 голос
/ 03 августа 2020

Если вы получаете все Obligation в наборе запросов и используете select_related, чтобы также получить связанные Car и Owner. Затем вы можете использовать itertools.groupby для перебора одного запроса при группировке по Owner

expired_obligations = Obligation.objects.filter(
    expiration_date__lte=date.today()
).select_related('car__owner').order_by('car__owner')

for owner, obligations in itertools.groupby(expired_obligations, lambda obligation: obligation.car.owner):
    print(owner, list(obligations))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...