Search code examples
pythondjangodjango-modelstastypie

Tastypie apply_filters with distinct


can someone help me out, I need a list of shares with only unique users, only the latest share pr. user (post__user)

I am using tastypie at API framework, hope someone can help me out, my model layout looks like this::

class Post(models.Model):
    user = models.ForeignKey(User)
    ....

class Share(models.Model):
    post = models.ForeignKey(Post)
    user = models.ForeignKey(User, blank=True, null=True)
    ....

My Tastypie resource:: with my example of code, but gives me ALL the shares, and not only one (the latest) pr. user .. hope someone can help.

class ShareResource(ModelResource):
    ....
    ....
    def apply_filters(self, request, applicable_filters):
        distinct = request.GET.get('distinct', False) == 'True'
        if distinct:
            d = self.get_object_list(request).filter(**applicable_filters).values_list("post__user", flat=True).distinct()
            return Share.objects.filter(post__user__id__in=d)
        else:
            return self.get_object_list(request).filter(**applicable_filters)

Solution

  • Hmm, seems like more of an ORM question.

    d is going to be a list of unique users who've shared anything at all, filtered by applicable_filters. You're then querying for Share objects that have been shared by someone in that list of users who've shared things; but this query will return Share objects that those users have shared that weren't in applicable_filters. Also, it will return duplicates.

    I think you want this:

    class ShareResource(ModelResource):
        ....
        ....
        def apply_filters(self, request, applicable_filters):
            distinct = request.GET.get('distinct', False) == 'True'
            if distinct:
                # need to order Share objects so that the most recent one comes first
                return self.get_object_list(request).filter(**applicable_filters).order_by('id', '-created').distinct('id')
            else:
                return self.get_object_list(request).filter(**applicable_filters)
    

    Note, this may only work on Postgres.