ListCreateAPIView not filtering by pk in the route

1,207 views
Skip to first unread message

Toran Billups

unread,
Nov 16, 2012, 10:35:03 AM11/16/12
to django-res...@googlegroups.com
I'm trying to filter down a list of speakers by a related (session) pk

here is my urls route

url(r'^/(?P<pk>\d+)/speakers/$', SpeakerList.as_view())

here is my view

class SpeakerList(generics.ListCreateAPIView):
    model = Speaker
    serializer_class = resources.SpeakerSerializer

here is my custom serializers

class SessionSerializer(serializers.ModelSerializer):
    speakers = serializers.ManyPrimaryKeyRelatedField()
    
    class Meta:
        model = Session
        fields = ('id', 'name', 'speakers')
    
class SpeakerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Speaker
        fields = ('id', 'name', 'session')

here is my models.py

class Session(models.Model):
    name = models.CharField(max_length=150)
    
class Speaker(models.Model):
    name = models.CharField(max_length=100)
    session = models.ForeignKey(Session, related_name='speakers')

When i hit that endpoint I'm getting all the speakers back (not just all speakers for a given session) 

[ {id: 1, name: foo, session: 1}, {id: 2, name: bar, session: 2} ]

I assumed the backend would use the pk (kwarg from the url) to filter this but ... clearly I was wrong :)

Any help would be greatly appreciated

Toran

Tom Christie

unread,
Nov 16, 2012, 11:08:51 AM11/16/12
to django-res...@googlegroups.com
The pk and/or slug kwargs are used to identify a given object in a detail view, they're not used to filter a queryset in a list view.

What you're looking for is this...


It's probably also taking a quick look at the source for get_object and get_queryset...


Tom Christie

unread,
Nov 16, 2012, 11:10:21 AM11/16/12
to django-res...@googlegroups.com
Also worth noting that this is the same behavior as Django's ListView and DetailView, so if you're used to using them, you can just work by the same rules.

Toran Billups

unread,
Nov 16, 2012, 11:26:49 AM11/16/12
to django-res...@googlegroups.com, t...@tomchristie.com
Tom

Awesome! thanks for the quick reply (didn't realize I missed this in the docs) 

Thanks again!

Toran

Toran Billups

unread,
Nov 16, 2012, 12:18:47 PM11/16/12
to django-res...@googlegroups.com, t...@tomchristie.com
Tom

The only hang up I had with this queryset re-work is that QUERY_PARAMS is always empty with the url route I had

<QueryDict: {}>

Anything I'm not seeing in the api docs that might help me fix this last issue?

Thank you in advance

Toran

**also slight note about a syntax error in the docs that I found

class PurchaseList(generics.ListAPIView)
    model = Purchase
    serializer_class = PurchaseSerializer

    def get_queryset(self):
        """
        Optionally restricts the returned purchases to a given user,
        by filtering against a `username` query parameter in the URL.
        """
        queryset = Purchase.objects.all()
        username = self.request.QUERY_PARAMS.get('username', None): **this will blow up (remove the un-needed : at the end)
        if username is not None:
            queryset = queryset.filter(purchaser__username=username)
        return queryset

My comments to fix the typo above might help another soul looking at the api docs :)

Toran

Tom Christie

unread,
Nov 16, 2012, 12:49:24 PM11/16/12
to django-res...@googlegroups.com, t...@tomchristie.com
> The only hang up I had with this queryset re-work is that QUERY_PARAMS is always empty with the url route I had

request.QUERY_PARAMS is just a more correct synonym for request.GET, it doesn't have anything to do with the URL kwargs.
(Although if those two really *are not* returning the same thing then that's an out-and-out bug?)
 
I think you want this:

http://django-rest-framework.org/api-guide/filtering.html#filtering-against-the-url

Rather than this:


> also slight note about a syntax error in the docs that I found

Noted and fixed, thank you!

Toran Billups

unread,
Nov 16, 2012, 1:00:55 PM11/16/12
to django-res...@googlegroups.com, t...@tomchristie.com
I added *args, **kwargs to the get_queryset as well with no luck

In addition self.request.GET is also an empty QueryDict :(

If this is a true bug should I dig into the source and pull request it in or have you already looked into the source on this / have an idea where this might be a problem?

thank you (again)

Toran

Tom Christie

unread,
Nov 16, 2012, 2:03:08 PM11/16/12
to django-res...@googlegroups.com
I added *args, **kwargs to the get_queryset as well with no luck

Use self.kwargs to access the URL kwargs inside a class based view.
(ie. adding **kwargs to the get_queryset signature won't do anything)
I'm pretty certain that example should work just fine,
and I would expect self.request.GET to be empty because your not adding any ?query=parameters to the URL. 
Anyway, have a dig around first and let us know how you get on.

Toran Billups

unread,
Nov 16, 2012, 2:31:35 PM11/16/12
to django-res...@googlegroups.com
That works! I'll use self.kwargs for the time being (and your point about the ?query checks out so I'll roll ahead with the kwargs approach for now)

Thanks for the quick / great feedback as always!

Toran
Reply all
Reply to author
Forward
0 new messages