Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I filter on a field in a related object?

If I try to filter on a field in a related object then Tastypie returns an error. For example, running

curl -H "Accept: application/json" \
     "http://localhost:8080/wordgame/api/v1/rounds/?format=json&players__username=moe"

returns "Lookups are not allowed more than one level deep on the 'players' field." Essentially, I am trying to do what I can currently do in the Django shell:

Round.objects.all().filter(players__username=moe.username)

I am using the following code, which I simplified for brevity:

# wordgame/api.py which has tastypie resources
class RoundResource(ModelResource):
    players = fields.ManyToManyField(UserResource, 'players',full=True)
    . . .

    class Meta:
        queryset = Round.objects.all()
        resource_name = 'rounds'
        filtering = {
            'players': ALL,
        }

class UserResource(ModelResource):
    class Meta:
        queryset = User.objects.all()
        resource_name = 'players'
        filtering = {
            'username': ALL,
        }

# wordgame/models.py which has Django models
class Round(models.Model):
    players = models.ManyToManyField(User)
    word = models.CharField(max_length=75)
    . . . 

I'm assuming that because UserResource defines a filter on the field 'username' that this should work but it does not. I even attempted to add "players__username" to the filter in RoundResource, however this did not work either.

I read about basic filtering in the docs and looked at the code on GitHub however there doesn't seem to be anything for this. I also took a look at the advanced filtering documentation and it doesn't seem to fit my use case. I've looked at the Tastypie code on GitHub but don't understand it enough to figure out if 1) I am doing this wrong, or 2) what to override to get this to work.

like image 993
Andrew Halloran Avatar asked Aug 10 '12 15:08

Andrew Halloran


1 Answers

Apparently, you need to specifically white-list the relation-spanning lookups in your filtering line, like this:

class UserResource(ModelResource):
    class Meta:
        queryset = User.objects.all()
        resource_name = 'players'
        filtering = {
            'username': ALL_WITH_RELATIONS,
        }

At least, I think that's the right place to put it. The relevant docs are fairly slim on examples. A Tastypie ticket, though, suggests this should work.

like image 74
supervacuo Avatar answered Nov 05 '22 03:11

supervacuo