Django禁止过滤模型以包括与第一个标准匹配的集合

时间:2014-09-12 22:46:04

标签: django django-queryset

我想迭代用户匹配的实体,以避免首先在辅助数组中进行分组。

如何通过这样的查询,我可以使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付款,而无需再次查询单个用户的付款。

1 个答案:

答案 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))

请务必阅读文档。