Django Queryset получает самую низкую/самую высокую цену! один ко многим

63
4

У меня есть некоторые модели Django, класс Product и класс Price. Продукт может иметь несколько цен, но только "новейший" - текущая цена! У меня есть запрос продукта, где мне нужна самая низкая цена и самая высокая цена, но только текущие цены. Если у продукта есть 2 и более цен, это только самая новая цена, которую я хочу!

class Product(models.Model):
productname = models.CharField(max_length=1024)

class Price(models.Model):
product = models.ForeignKey(Product)
price = models.DecimalField(max_digits=10, decimal_places=2)
created = models.DateTimeField(auto_now_add=True)

Пример в наборе запросов, где мне нужны самые низкие и самые высокие, но только текущие цены. То же самое для "price__price__gt". Это также должно быть только текущие цены, с которыми я хочу работать.

Product.objects.filter(price__price__gt=1000).order_by("price")

спросил(а) 2021-01-25T23:32:04+03:00 4 месяца, 3 недели назад
1
Решение
89

Вот один из способов получить продукт с минимальной ценой.

Создайте свойство current_price в модели продукта,

class Product(models.Model):
productname = models.CharField(max_length=1024)

@property
def current_price(self):
"""Returns last price if any prices exist, else None
"""
if self.price.all():
return self.price.order_by('-created')[0].price

чтобы свойство current_price работало правильно, вам нужно добавить имя, связанное с ценой, в поле fk продукта модели цены,

class Price(models.Model):
product = models.ForeignKey(
Product, related_name='price')
price = models.DecimalField(max_digits=10, decimal_places=2)
created = models.DateTimeField(auto_now_add=True)

Теперь вы можете фильтровать минимальную цену следующим образом:

qs = [p for p in Product.objects.all() if p.current_price]
# Returns a list of products that have a current price

# To get the lowest price,
cheapest_product = min(qs, key=lambda x: x.current_price)
cheapest_product.current_price

# To get the highest price,
most_expensive_product = max(qs, key=lambda x: x.current_price)
most_expensive_product.current_price

Вы можете сделать диспетчер моделей, чтобы сделать это за вас, см. Django docs для получения дополнительной информации.

Желательно, чтобы менеджер, который мог работать таким образом,

Product.objects.cheapest()  # returns the single cheapest 'current' price.
Product.objects.most_expensive() #returns most expensive (highest) price

ответил(а) 2021-01-25T23:32:04+03:00 4 месяца, 3 недели назад
77

Это должно сделать трюк.


from django.db.models import Max

prods_with_prices = []
for prod in Product.objects.all():
prices = Prices.objects.filter(product = prod).annotate(current_price=Max('created'))
prods_with_prices.append({'product': prod, 'price': prices.current_price})
costly_prod = max(prods_with_prices, key = lambda x: x['price'])['product']
cheap_prod = min(prods_with_prices, key = lambda x: x.['price'])['product']

print "Most expensive product: " + costly_prod
print "Least expensive product: " + cheap_prod

ответил(а) 2021-01-25T23:32:04+03:00 4 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема