对于列表查询,我想显示特定网站上特定产品的价格。
我已经找到了一种使用RawSQL的方法,这是我以前从未做过的事情。我忽略了什么吗?
queryset = Price.objects.all()
site_annotations = {}
for site in Site.objects.all():
site_annotations['num_prices_{}'.format(site.name)] = RawSQL(
'SELECT COUNT(id) '
'FROM `product_siteprice` '
'WHERE `product_siteprice`.`price_id` = `product_price`.`id` '
'AND site_id=%s', [site.pk]
)
queryset = queryset.annotate(**site_annotations)
修改
我的模型看起来像这样简化:
class Site(Model):
name = models.CharField(_('display name'), max_length=50)
class Price(Model):
name = models.CharField()
class SitePrice(Model):
price = models.ForeignKey(Price)
site = models.ForeignKey(Site)
现在我想要的表是:
Product | Nr of prices on Site A | Nr of prices on Site B |
--------|------------------------|------------------------|
Iphone | 6 | 3 |
Xperia | 42 | 66 |
我想对价格数量进行排序和过滤,这就是我需要注释的原因。
注意如果你不了解其余的背景,价格有点误导,在这种情况下它可以看作更像产品
答案 0 :(得分:0)
根据我的理解,您只需要过滤相关网站上的价格,然后获取对象数量的计数。
Price.objects.filter(site_price__site_id=site.pk).count()
虽然您可能只想删除网站价格模型并将其替换为多对多字段
答案 1 :(得分:0)
我认为您想要的查询看起来像这样:
qs = SitePrice.objects.values('price_id', 'site_id').annotate(d_count=Count('id'))
为了获得你想要的表格,你可以将它格式化成一个类似这样的字典:
from collections import defaultdict
values = defaultdict(dict)
for x in qs:
values[ x['price_id'] ][ x['site_id'] ] = x['d_count']
要打印此表,您可以使用:
price_ids = list(values.keys()) # you don’t need `list` for python 2
site_ids = set()
for x in values.values():
site_ids |= set(x.keys())
site_ids = list(site_ids)
site_ids.sort()
prices = dict(Price.objects.filter(id__in=price_ids).values_list('id', 'name'))
sites = dict(Site.objects.filter(id__in=site_ids).values_list('id', 'name'))
print(' ', end='') # for python 3
# print ' ', # for python 2
for x in site_ids:
print('%-8s ' % sites[x], end='')
print('')
for x, counts in values.items():
print('%-8s ' % prices[x], end='')
for site_id in site_ids:
d_count = counts.get(site_id, 0)
print('%-8s ' % d_count, end='')
print('')