Django - Получение последних из каждого выбора - PullRequest
0 голосов
/ 28 января 2020

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

   class GasStation(models.Model):
        place_id = models.IntegerField(primary_key=True)
        name = models.CharField(max_length=255, null=True, blank=True)

    class Price(models.Model):

        class Producto(models.TextChoices):
            GASOLINA_REGULAR = 'GR', _('Gasolina regular')
            GASOINA_PREMIUM = 'GP', _('Gasolina premium')
            DIESEL_REGULAR = 'DR', _('Diesel regular')
            DIESEL_PREMIUM = 'DP', _('Diesel premium')

        product = models.CharField(max_length=2, choices=Producto.choices)
        created = models.DateTimeField(auto_now_add=True)
        updated = models.DateTimeField(auto_now=True)
        price = models.FloatField(null=True, blank=True)
        estacion = models.ForeignKey(GasStation,
                             on_delete=models.SET_NULL,
                             null=True,
                             related_name='prices')

Я пробовал:

station.price.filter(product__in=['GR', 'GP', 'DR', 'DP']).latest()

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

1 Ответ

2 голосов
/ 28 января 2020

Вы ищете аннотации и подзапрос . Ниже я думаю, что это может сработать. Ваши модели не полностью определены. Если вам нужен весь экземпляр Price, то это не сработает для вас. Подзапрос может аннотировать только одно поле.

from django.db.models import OuterRef, Subquery
stations = GasStation.objects.annotate(
    latest_regular=Subquery(
        Price.objects.filter(station_id=OuterRef("pk"), product="GR").order_by('-updated').values("price")[:1]
    ),
    latest_premium=Subquery(
        Price.objects.filter(station_id=OuterRef("pk"), product="GP").order_by('-updated').values("price")[:1]
    ),
    ...
)

station = stations.get(something_here)
station.latest_premium, station.latest_regular

Вы можете сделать это более кратким, используя сложное понимание, повторяя короткие коды вашего Продукта и затем .annotate(**annotations)

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