Join Multiple Querysets From Different Base Models Django
Asked Answered
A

3

23

I currently have two different models.

class Journal(models.Model):
    date = models.DateField()
    from_account = models.ForeignKey(Account,related_name='transferred_from')
    to_account = models.ForeignKey(Account,related_name='transferred_to')
    amount = models.DecimalField(max_digits=8, decimal_places=2)
    memo = models.CharField(max_length=100,null=True,blank=True)

class Ledger(models.Model):
    date = models.DateField()
    bank_account = models.ForeignKey(EquityAccount,related_name='paid_from')
    account = models.ForeignKey(Account)
    amount = models.DecimalField(max_digits=8, decimal_places=2)
    name = models.ForeignKey(Party)
    memo = models.CharField(max_length=100,null=True,blank=True)

I am creating a report in a view and get the following error: Merging 'ValuesQuerySet' classes must involve the same values in each case.

What I'm trying to do is only pull out the fields that are common so I can concatenate both of them e.g.

def report(request):

    ledger = GeneralLedger.objects.values('account').annotate(total=Sum('amount'))
    journal = Journal.objects.values('from_account').annotate(total=Sum('amount'))
    report = ledger & journal
...

If I try to make them exactly the same to test e.g.

def report(request):

    ledger = GeneralLedger.objects.values('memo').annotate(total=Sum('amount'))
    journal = Journal.objects.values('memo').annotate(total=Sum('amount'))
    report = ledger & journal
...

I get this error: Cannot combine queries on two different base models.

Anyone know how this can be accomplished?

Ailssa answered 18/7, 2011 at 11:36 Comment(0)
E
38
from itertools import chain
report = chain(ledger, journal)

Itertools for the win!

If you want to do an Union, you should convert these querysets into python set objects.

If it is possible to filter the queryset itself rightly, you should really do that!

Endue answered 18/7, 2011 at 11:50 Comment(1)
I'm getting this: AttributeError: 'itertools.chain' object has no attribute 'model'Shetrit
R
8

Use itertools.chain:

from itertools import chain
report = list(chain(ledger, journal))

Note: you need to turn the resulting object into a list for Django to be able to process it.

Resurrectionism answered 14/9, 2018 at 11:42 Comment(0)
D
3

I had the same issue. I solved it using the union method combined_queryset = qs1.union(qs2)

Using your example: report = ledger.union(journal)

Despotism answered 11/7, 2022 at 18:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.