MooCow
MooCow

Reputation: 1426

Django Rest Framework : Pagination with annotated Queryset

I am currently doing a project which requires pagination. A list of Images is provided to the user and whether they were Favorited or not by user.

Favorited Images are kept in a separate table.

In order to provide a list of images and ones that were Favorited by the user an annotate.

    def _get_queryset(self, request):
      user_favorited = DjImagingImagefavorites.objects.filter(ifv_img_recordid__exact=OuterRef('pk'), ifv_user_id__exact=request.user.profile)
      queryset = DjImagingImage.objects.all().annotate(favorited=Exists(user_favorited))
      return queryset

Then in the list function

    def list(self, request):
      images = self._get_queryset(request)
      page = self.paginate_queryset(images) #Breaks here

The Query then throws an error. ]Cannot use an aggregate or a subquery in an expression used for the group by list of a GROUP BY clause.

Due to an oddities of how the paginate function performs the count and constructs an illegal sql statement.

Question is - Is their a better way about going to do this or should this work perfectly as I thought it should have?

Upvotes: 3

Views: 1518

Answers (1)

MooCow
MooCow

Reputation: 1426

A solution that I found works is coded below

 def list(self, request):
   images = self._get_queryset(request)
   #page = self.paginate_queryset(images)
   return self.paginate(images)

I create a wrapper called paginate

def paginate(self, queryset):
    """Calculate paginated QuerySet and wrap in a Response.

    Args:
        queryset - the queryset to be paginated
    """
    page = self.paginate_queryset(queryset)
    if page is not None:
        serializer = self.get_serializer(page, many=True)
        return self.get_paginated_response(serializer.data)
    serializer = self.get_serializer(queryset, many=True)
    return Response(serializer.data)

For those who are wondering the queryset I am constructing

def get_queryset(self):
    """Return the modified/prepared master QuerySet.

    Returns:
        QuerySet<DjImagingImage>: The modified master QuerySet

    """
    return DjImagingImage.objects.annotate(
            mine=FilteredRelation('djimaginguserspecifics',condition=Q(djimaginguserspecifics__usp_emp_employeeid=self.request.user.profile)),
            usp_favorite=F('mine__usp_favorite'),
            usp_inhistory=F('mine__usp_inhistory'),
            usp_emp_employeeid=F('mine__usp_emp_employeeid'),
            usp_lastviewed=F('mine__usp_lastviewed'),
            comment_count=Count('djimagingimagecomment'))

Upvotes: 1

Related Questions