gregdevs
gregdevs

Reputation: 713

django rest frameworks - querying to a nested List?

Working with DRF and curious as to whether you can query over a nested item like a list. For example, being able to filter against a query parameter like: http://someurl.com?hashtags=cool

{
    "id": 1,
    "author": 1,
    "hashtags": [
        "cool", "gross"
    ],
    "username": "johndoe"

}

I have checked out Django Filters, and was looking for something DRF-specific, kind of like: hashtags = django_filters.filters.CharFilter(name="hashtags") but for iterating over a nested List. Obviously CharFilter wouldn't be correct.

Thanks for any tips or ideas.

-Updated-

The filter obviously does not work but, what was where I was trying to go

views.py

class MentionLatFilter(django_filters.FilterSet):
    hashtags = django_filters.filters.SomeFilter(name="hashtags")

    class Meta:
        model = Mention
        fields = ['hashtags']


class MentionList(generics.ListAPIView):
    serializer_class = MentionSerializer  
    filter_backends = (filters.DjangoFilterBackend,)
    filter_class = MentionLatFilter       


    def get_queryset(self):
        queryset = Mention.objects.all()
        placename = self.request.query_params.get('placename', None)
        if placename is not None:
            queryset = queryset.filter(placename=placename)

        username = self.request.query_params.get('username', None)
        if username is not None:
            queryset = queryset.filter(username=username)  

        return queryset

models.py

class Mention(models.Model):
    author = models.ForeignKey(User)
    username =  models.CharField(max_length=140, default='Username')
    placename = models.CharField(max_length=140, default='SOME STRING')
    placemention = models.TextField(max_length=140, default='SOME STRING')
    lat = models.DecimalField(max_digits=20, decimal_places=15)
    lng = models.DecimalField(max_digits=20, decimal_places=15)
    created_date = models.DateTimeField(
            default=timezone.now)
    published_date = models.DateTimeField(
            blank=True, null=True)

    def publish(self):
        self.published_date = timezone.now()
        self.save()

    def __str__(self):
        return self.placename



class Hashtag(models.Model):
    mention = models.ForeignKey(Mention, related_name='hashtags')
    tagname = models.CharField(max_length=100)

    class Meta:
        unique_together = ('mention', 'tagname')

    def __unicode__(self):
        return '%s' % (self.tagname)

Upvotes: 0

Views: 490

Answers (1)

Rohit Jain
Rohit Jain

Reputation: 213311

You don't need a custom filter here. Django queryset can follow the reverse relationship very well, for filtering. Check this link: https://docs.djangoproject.com/en/1.8/topics/db/queries/#lookups-that-span-relationships

Here's how you would modify your get_queryset() method:

class MentionList(generics.ListAPIView):
    def get_queryset(self):
        hashtag_filter = self.request.query_params.get('hashtags', None)
        return Mention.objects.filter(hashtag__tagname=hashtag_filter)

Upvotes: 1

Related Questions