我想迭代用户匹配的实体,以避免首先在辅助数组中进行分组。
如何通过这样的查询,我可以使User.stone_set只包含与过滤器匹配的那些?
users = User.objects.filter(payment__due_day__lte=datetime.today()+3)
现在每个用户都应该只有匹配过滤器的付款实例,但users.payment_set是一个与之无关的经理。
澄清
这是我的模特:
class Payment(models.Model):
owner = models.ForeignKey(User)
due_day = models.IntegerField()
现在,查询如下:User.objects.filter(payment__due_day=10)
将为我提供截止到期日10的用户。现在迭代这些用户对象,我希望它只有我第一次查询的那些付款(只有那些有使用due_day = 10付款,而无需再次查询单个用户的付款。
答案 0 :(得分:3)
如果我理解你的问题,最后你想要一个Payment
个对象的查询集。
然后,从该模型开始,而不是User
。
payments = Payment.objects.filter(due_day=10).select_related('owner').order_by('owner')
之后,您可以迭代查询集并获取每笔付款的所有者(用户),而无需任何额外查询,因为select_related
将在后台为您执行SQL连接。
如果您为每个用户多次付款,则需要order_by
子句,并且您需要显示该条款。在模板中,您可以使用regroup
内置模板标记。
例如:
# In your view (EXTREMELY simplified)
def my_view(request):
payments = Payment.objects.filter(due_day=10).select_related('owner').order_by('owner')
return render_to_response('template.html', {'payments': payments})
# In your template
{% regroup payments by owner as payment_list %}
<ul>
{% for payment in payment_list %}
<li>{{ payment.grouper }} <!-- this is the owner -->
<ul>
{% for item in payment.list %}
<li>{{ item.due_day }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
相反,如果你想在裸python中实现这一点,最好的解决方案是使用itertools.groupby
(事实上,regroup
标签使用它。)
一个快速且未经测试的例子:
from itertools import groupby
from operator import attrgetter
payments = Payment.objects.filter(due_day=10).select_related('owner').order_by('owner')
for owner, grouped_payments in groupby(payments, attrgetter('owner')):
do_stuff_with(owner)
do_some_other_stuff_with(list(grouped_payments))
请务必阅读文档。