Crazyconoli
Crazyconoli

Reputation: 671

Join Multiple Querysets From Different Base Models Django

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?

Upvotes: 25

Views: 30420

Answers (3)

bnmounir
bnmounir

Reputation: 91

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

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

Upvotes: 3

Tim G
Tim G

Reputation: 91

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.

Upvotes: 9

lprsd
lprsd

Reputation: 87077

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!

Upvotes: 40

Related Questions