Django paginator page turns to list

I'm trying built a matrimonial site in Django. The following is the code for displaying a single profile at a time.
unfiltered_list = profile_matches
for profile in unfiltered_list:
print("\n profile:",profile,"\n")
profiles_list = profile_matches
paginator = Paginator(profiles_list,1)
page_number = request.GET.get('page', 1)
profiles = paginator.page(page_number)
profile_id = profiles.object_list.values('user_model_for_profile_id')
The code works fine if I remove the for loop, but when I try to loop through the unfiltered list, 'profiles' becomes a list even though I haven't touched it, other than creating a variable that references to it. I get an Attribute error saying AttributeError: 'list' object has no attribute 'values'
Is this a problem with Django itself? Or am I missing something?
Answer
This is indeed the case, the reason this happens is because the Paginator
in Django slices the queryset [GitHub], indeed:
def page(self, number): """Return a Page object for the given 1-based page number.""" # … return self._get_page(self.object_list[bottom:top], number, self)
and this will return a QuerySet
if the original QuerySet
has no result_cache
.
But if the QuerySet
has results loaded into memory, it returns the sliced result cache [GitHub], indeed:
def __getitem__(self, k): """Retrieve an item or slice from the set of results.""" # … if self._result_cache is not None: return self._result_cache[k] # …
since the ._result_cache
is a list of results, the result will indeed be a list.
Pagination is normally the end of the process, so extra ORM calls are quite strange. Moreover, using .values()
is a bit of an anti-pattern [django-antipatterns].
If you want to first enumerate over the data, enumerate over a clone of the queryset, so:
for profile in unfiltered_list.all():
print('\n profile:', profile, '\n')
Enjoyed this article?
Check out more content on our blog or follow us on social media.
Browse more articles