Reputation: 552
I want to iterate over user matching entities to avoid grouping in helper array first.
How from query like this I can make User.stone_set to contain only ones that matched the filter?
users = User.objects.filter(payment__due_day__lte=datetime.today()+3)
Now each user should have only payment instances that mateched the filter, but users.payment_set is a manager not really related to it.
Clarification
Here is my model:
class Payment(models.Model):
owner = models.ForeignKey(User)
due_day = models.IntegerField()
now, query like this: User.objects.filter(payment__due_day=10)
will give me users that have payment due day 10. Now iterating over those users objects I want it to have only those payment I queried for the first time (only those that have payment with due_day = 10), without quering single user again for their payments.
Upvotes: 1
Views: 96
Reputation: 2482
If I understand your question, in the end you want a queryset of Payment
objects.
Then, start from that model, not User
.
payments = Payment.objects.filter(due_day=10).select_related('owner').order_by('owner')
After that, you can iterate over the queryset and get the owner (user) of each payment without any extra query, because select_related
will do a SQL join for you in the background.
The order_by
clause is needed if you have multiple payments for each user and you need to show that. In your template you can use the regroup
built-in template tag.
For example:
# 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>
If, instead, you want to achieve that in bare python, the best solution is to use itertools.groupby
(which is, in fact, used by the regroup
tag).
A quick and untested example:
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))
Be sure to read the docs.
Upvotes: 3