0

I want to concatenate two queryset obtained from two different models and i can do it using itertools like this:

ci = ContributorImage.objects.all()
pf = Portfolio.objects.all()
cpf = itertools.chain(ci,pf)

But the real fix is paginating results.If i pass a iterator(cpf, or our concatenated queryset) to Paginator function, p = Paginator(cpf, 10), it works as well but fails at retrieving first page page1 = p.page(1) with an error which says:

TypeError: object of type 'itertools.chain' has no len()

What can i do in case like this ?

mariodev
  • 13,928
  • 3
  • 49
  • 61
vijay shanker
  • 2,517
  • 1
  • 24
  • 37
  • I know if i evaluate ci pf by wraping them in list(), this will solve my objective but i guess that will bloat memory and will be inefficient, correct me if i am wrong. – vijay shanker Jan 22 '14 at 14:29

2 Answers2

1

The itertools.chain() will return a generator. The Paginator class needs an object implementing __len__ (generators, of course do not support it since the size of the collection is not known).

Your problem could be resolved in a number of ways (including using list to evaluate the generator as you mention) however I recommending taking a look at the QuerySetChain mentioned in this answer:

https://stackoverflow.com/a/432666/119071

I think it fits exactly to your problem. Also take a look at the comments of that answer - they are really enlightening :)

Community
  • 1
  • 1
Serafeim
  • 14,962
  • 14
  • 91
  • 133
  • Using list() to evaluate the generator is a neat solution, worked for me in a similar case, thanks. – Rickka Jul 27 '16 at 08:59
0

I know it's too late, but because I encountered this error, I would answer to this question.

you should return a list of objects:

ci = ContributorImage.objects.all()
pf = Portfolio.objects.all()
cpf = itertools.chain(ci,pf)

cpf_list = list(cpf)
Ali
  • 2,541
  • 2
  • 17
  • 31