Проблема с запросами в Django Rest Framework при использовании filter()
вот моя модель:
class PmPrice(models.Model):
created_at = models.DateTimeField()
price = models.DecimalField(max_digits=6, decimal_places=2)
listing = models.ForeignKey("PmListing", models.DO_NOTHING)
seller = models.ForeignKey("PmSeller", models.DO_NOTHING)
class Meta:
managed = False
db_table = "pm_price"
вот мой сериализатор:
class PmPriceListSerializer(serializers.ModelSerializer):
url = serializers.ReadOnlyField(source="listing.url")
shop = serializers.ReadOnlyField(source="listing.shop.name")
name = serializers.ReadOnlyField(source="listing.product.name")
ean = serializers.ReadOnlyField(source="listing.product.ean")
uvp = serializers.ReadOnlyField(source="listing.product.uvp")
sku = serializers.ReadOnlyField(source="listing.product.sku")
seller = serializers.ReadOnlyField(source="seller.name")
class Meta:
model = PmPrice
fields = (
"url",
"shop",
"name",
"ean",
"sku",
"uvp",
"price",
"created_at",
"seller",
)
def to_representation(self, instance):
data = super().to_representation(instance)
return data
а это метод внутри моего класса filters.py, который я использую в своем представлении, и это вызывает у меня головную боль:
def get_by_last_two_cheapest(self, queryset, name, value):
latest_date_subquery = (
queryset.annotate(datum=TruncDate("created_at"))
.values("datum")
.order_by("-datum")
.annotate(latest_date=Max("datum"))
.values("latest_date")[:1]
)
# Second subquery to get the second latest date
second_latest_subquery = (
queryset.filter(
created_at__date__lt=Subquery(latest_date_subquery),
)
.annotate(datum=TruncDate("created_at"))
.values("datum")
.order_by("-datum")
.annotate(latest_date=Max("datum"))
.values("latest_date")[:1]
)
# Concatenate the results of the subqueries to get the dates
dates = list()
dates.append(str(latest_date_subquery[0]["latest_date"]))
dates.append(str(second_latest_subquery[0]["latest_date"]))
print(dates)
# Perform the necessary filtering and annotation
qs = (
queryset.filter(created_at__date__in=dates)
.values("listing_id", "created_at__date")
.annotate(cheapest_price=Min("price"))
)
print(qs)
print(len(qs))
# Retrieve the corresponding rows with the cheapest prices
result_queryset = queryset.filter(
created_at__date__in=dates,
listing_id__in=qs.values_list("listing_id", flat=True),
price__in=qs.values_list("cheapest_price", flat=True),
).order_by("-created_at", "listing_id")
print(len(result_queryset))
return result_queryset
Теперь я хочу получить самую дешевую цену для listing_id
на последнюю created_at
дату, а также вторую последнюю created_at date
. Поэтому я запрашиваю даты, помещаю их в список, затем получаю cheapest_price
для этих дат (в qs
), а затем хочу получить result_queryset
со всеми объектами, которые мне нужно вернуть.
Для created_at
даты может быть несколько цен на одну и ту же listing_id
дату, но мне нужна только cheapest
одна (Min()
), поэтому я создаю qs
подзапрос. Подзапрос qs
содержит 60 результатов, что правильно. Но result_queryset
содержит 61 результат, и я понял, почему. Потому что он извлекает дополнительный объект, в котором совпадает created_at
дата, listing_id
совпадает И его price
находится внутри qs.values_list("cheapest_price")
- только не в комбинации created_at+listing_id+cheapest_price.
Так что если я добавлю в таблицу базы данных одну строку, соответствующую допустимому listing_id
, created_at
и любому cheapest_price
, который находится внутри qs
, я получу еще один дополнительный объект. Как это исправить?
thx