假设我有一个带这些模型的简单购物车系统:
from django.db import models
from django.utils import timezone
class Product(models.Model):
name = models.CharField(max_length=255)
# More fields...
@property
def featured_image(self):
try:
return self.productimage_set.all()[0]
except IndexError:
return None
def __str__(self):
return self.name
class ProductImage(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
image = models.FileField(upload_to='products/')
# More fields...
def __str__(self):
return self.product.name
class Order(models.Model):
created = models.DateTimeField(default=timezone.now)
# More fields...
def __str__(self):
return str(self.pk)
class OrderItem(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField()
# More fields...
def __str__(self):
return 'Order %s: %s of %s' % (
self.order_id,
self.quantity,
self.product.name,
)
当用户下订单时,会为他们订购的每件商品创建一个OrderItem
对象,这让我知道(1)他们购买了哪种产品,以及(2)他们购买了多少产品。
现在,假设我想向用户显示他们最常订购的产品。我将以此数据为例:
Order 1:
Product A: 10
Order 2:
Product A: 10
Product B: 5
Order 3:
Product A: 10
Product B: 5
Product C: 5
此特定用户应按此顺序显示产品:
Product A: 30 total
Product B: 10 total
Product C: 5 total
这是实现此目的的代码:
order_items_by_quantity = OrderItem.objects.values(
'product__name',
).annotate(
total_purchased=Sum('quantity'),
).order_by(
'-total_purchased',
)
for order_item in order_items_by_quantity:
print(order_item)
但是使用这种方法,我无法使用order_item.product.featured_image
。有没有办法可以同时拥有这两种东西?也就是说,所有数量都是从大多数到最少总结和排序的和使用order_item.product.featured_image
的能力。
答案 0 :(得分:0)
nesterovs_momentum
答案 1 :(得分:0)
我认为在使用values()
之后有一种获取对象属性的方法,因为查询集返回带有SELECT键值的dicts,而不是模型对象。您可以执行其他查询以获取包含精选图片的产品,并将其映射到order_items
:
order_items_by_quantity = OrderItem.objects.values(
'product__name', 'product_pk'
).annotate(total_purchased=Sum('quantity')).order_by('-total_purchased')
product_image_map = {}
for product in Product.objects.prefetch_related('productimage_set'):
product_image_map[product.pk] = product.featured_image
for order_item in order_items_by_quantity:
order_item['featured_image'] = product_image_map[order_item['product_id']]
这样你就可以向数据库询问一次产品,而不是每次迭代order_items_by_quantity
。此外,您应该对图片进行prefetch_related()
。