Как найти записи в базе данных, действительные с определенной даты

Требование

У меня есть проект, в котором я хочу хранить список цен для данного продукта, которые должны быть действительны после определенной даты. 'current_price' должна отображаться на странице администрирования списка продуктов (в зависимости от даты запроса)

Проблема

Моя текущая реализация приводит к чрезмерным запросам к базе данных

Пример

цены на продукцию с течением времени

Product valid from Price
1 2022-03-01 100 EUR
1 2022-04-01 120 EUR
1 2022-05-01 130 EUR
2 2022-03-01 30 EUR
2 2022-04-01 40 EUR
2 2022-05-01 50 EUR

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

например, в 2022-03-15

PRODUCT CODE NAME CURRENT PRICE
2 Second product 30.00
1 First Product 100.00

например, на 2022-04-30

PRODUCT CODE NAME CURRENT PRICE
2 Second product 40.00
1 First Product 120.00

Код (рабочий)

Я получаю желаемые результаты при использовании следующего кода:

models.py

from django.db import models

class Product(models.Model):
    product_code = models.PositiveIntegerField(primary_key=True)
    name = models.CharField(max_length=100)

    def __str__(self) -> str:
        return self.name

class ProductPrice(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='prices')
    valid_from = models.DateField()
    price = models.DecimalField(max_digits=8, decimal_places=2)

    class Meta:
        get_latest_by = 'valid_from'

admin.py

from django.contrib import admin
from . import models
import datetime

@admin.register(models.Product)
class ProductAdmin(admin.ModelAdmin):
    list_display= ['product_code','name', 'current_price']

    def current_price(self,product):
        current_date = datetime.datetime.now()
        return product.prices.filter(valid_from__lte=current_date).latest().price

    def get_queryset(self, request):
        return super().get_queryset(request).prefetch_related('prices')

@admin.register(models.ProductPrice)
class ProductPriceAdmin(admin.ModelAdmin):
    list_display=['product','valid_from', 'price']

Однако, это решение приводит к куче запросов к базе данных, так как фильтрация по valid_from__lte=current_date выполняется для каждого отдельного продукта:

1-й запрос

SELECT `playground_productprice`.`id`,
       `playground_productprice`.`product_id`,
       `playground_productprice`.`valid_from`,
       `playground_productprice`.`price`
  FROM `playground_productprice`
 WHERE `playground_productprice`.`product_id` IN (2, 1)

следующие запросы

повторяется для каждого product_id

SELECT `playground_productprice`.`id`,
       `playground_productprice`.`product_id`,
       `playground_productprice`.`valid_from`,
       `playground_productprice`.`price`
  FROM `playground_productprice`
 WHERE (`playground_productprice`.`product_id` = 2 AND `playground_productprice`.`valid_from` <= '2022-04-30')
 ORDER BY `playground_productprice`.`valid_from` DESC
 LIMIT 1

Есть ли лучший способ решить эту проблему?

Вернуться на верх