我想在模板的for循环中显示每个帐户的统计信息。在字典或查询集列表中。
我有3种模型:(1)AdvertisingAccount,(2)Campaign,UserProfile。 我需要使用外键对属于某些AdvertisingAccounts的Campaigns的点击和视图求和。 (AdvertisingAccount也属于UserProfile)
我正在尝试检索,计算新的键值并将其添加到queryset的字典,但是似乎我无法在dict方法中做到这一点……
views.py
def ad_accounts(request):
user = request.user
accounts = user.userprofile.advertising_accounts.all()
accounts = accounts.values()
for d in accounts:
d.update(('clicks', d.campaigns.all().aggregate(Sum('clicks')) ) for k,v in d.items())
d.update(('views', d.campaigns.all().aggregate(Sum('views')) ) for k,v in d.items())
models.py
class AdvertisingAccount(models.Model):
balance = models.DecimalField(max_digits=12, decimal_places=2, default=0, blank=True, null=True)
foreign_system_name = models.CharField(max_length=30, blank=True, default=None)
foreign_system_id = models.IntegerField(default=None, blank=True, null=True)
def __str__(self):
return self.foreign_system_name + '--' + str(self.foreign_system_id)
class Campaign(models.Model):
userprofile = models.ForeignKey('users.UserProfile', on_delete=models.PROTECT, related_name='campaigns')
trade = models.ForeignKey('payments.Trade', on_delete=models.PROTECT, related_name='campaigns')
ad_account = models.ForeignKey('AdvertisingAccount', on_delete=models.PROTECT, related_name='campaigns')
views = models.IntegerField(default=0, blank=True, null=True)
clicks = models.IntegerField(default=0, blank=True, null=True)
ad_spent = models.DecimalField(max_digits=12, decimal_places=2, default=0, blank=True, null=True)
def __str__(self):
return str(self.userprofile) + '--' + str(self.ad_account.foreign_system_name) + '--' + str(self.trade.ad_budget)
模板
{% for i in accounts %}
{{i.clicks}}
{{i.views}}
{% endfor %}
我收到错误消息:'dict' object has no attribute 'campaigns'
由于我无法从模板检索过滤的数据,因此我试图构建自定义查询集或字典列表。整个方法正确吗?如何解决我的问题?
答案 0 :(得分:5)
请手动进行不注释,您可以简单地使用Django的.annotate(..)
method [Django-doc]。您甚至在这里使用了生成器,它会导致针对单个Account
模型的查询时间很多。
from django.db.models import Sum
accounts = user.userprofile.advertising_accounts.annotate(
clicks=Sum('campaigns__clicks'),
views=Sum('campaigns__views')
)
以上内容将生成QuerySet
个AdvertisingAccount
,并具有额外的属性.clicks
和.views
。实际上,该错误完全是因为您最初没有使用AdvertisingAccount
,而是使用字典(这些字典源自.values()
,因此您失去了关系的上下文)。
注释将在单个查询中运行,Django将在其中进行如下查询:
SELECT advertising_acount.*,
SUM(campaign.clicks) AS clicks,
SUM(campaign.views) AS views
FROM advertising_acount
LEFT OUTER JOIN campaign ON campaign.ad_account_id = advertising_acount.id
GROUP BY advertising_acount.id
这比汇总 per AdvertisingAccount
更为有效,因为那样的话,您将在这里使用 n 2n + 1 次。 > AdvertisingAcount
的数量。
因此,通常在字典上使用模型实例通常总是更好:模型类允许您定义方法,属性,添加关系等。它还保存对象的类型(例如{ 1}}),而具有相同键的两个字典本身并不源自相同的模型。字典只是将字段名称映射到相应数据库值的简单结构。因此,您“失去了”很多上下文。