Julia
Julia

Reputation: 325

Combine filter results in for loop

I'm using Django to make a website. I want to combine multiple filter results (Querysets).

My models' relationship

'Staff' 1:m 'Member' 1:m 'PaymentHistory' 1:1 'RefundHistory'

My view.py:

wanted_refund = set()
for m in staff.members.all():
    payment = m.PaymentHistory.filter(division="Membership")
    for p in payment:
        try:
            refund = RefundHistory.objects.filter(payment=p).filter(refund_date__range=[this_month_start, date])

            wanted_refund.add(refund)
        except RefundHistory.DoesNotExist:
            pass
 context = {
             'wanted_refund' : wanted_refund,}
    return render(request, 'refund.html', context)

But, it doesn't work by using filters. It only works when I use 'get'.

print(refund) shows me the result like this:

 < QuerySet [] >

 < QuerySet [] >

 < QuerySet [] >

 < QuerySet [< RefundHistory: RefundHistory object >] >

I want to use only the Querysets that have the object and what I want is the below one in template:

{% for refund in wanted_history %}
 {{ refund.refund_date }}
 {{ refund.refund_amount}}
 {% endfor %}

How do I pass over the multiple filters results in for loop?

Upvotes: 1

Views: 1028

Answers (2)

mattjegan
mattjegan

Reputation: 2884

It is possible to get the refund history for every payment of every member using a single query of the RefundHistory:

payments = []
for m in staff.members.all():
    payments.extend(m.PaymentHistory.filter(division="Membership").values_list('pk', flat=True))

wanted_refund = RefundHistory.objects.filter(payment__pk__in=payments, refund_date__range=[this_month_start, date])

context = {'wanted_refund' : wanted_refund,}
return render(request, 'refund.html', context)

Upvotes: 1

bakatrouble
bakatrouble

Reputation: 1844

You could join querysets using pipe operator:

wanted_refund = RefundHistory.objects.none()
for m in staff.members.all():
    payment = m.PaymentHistory.filter(division="Membership")
    for p in payment:
        try:
            wanted_refund |= RefundHistory.objects.filter(payment=p).filter(refund_date__range=[this_month_start, date])
        except RefundHistory.DoesNotExist:
            pass
wanted_refund = wanted_refund.distinct()
context = {'wanted_refund': wanted_refund}
return render(request, 'refund.html', context)

Also, if it will work for you, you may just use wanted_refund.update(list(refund)) in place of wanted_refund.add(refund)

Upvotes: 3

Related Questions