How to filter ToManyField of django-tastypie by re

2020-03-04 08:47发布

问题:

I'm building an API with tastypie for a django app for data based on the user. The resources are like this:

class PizzaResource(ModelResource):
    toppings = fields.ToManyField(
                'project.app.api.ToppingResource', 
                'topping_set'
            )

    class Meta:
        authentication = SessionAuthentication()
        queryset = Pizza.objects.all()

    def apply_authorization_limits(self, request, object_list):
        return object_list.filter(users=request.user)


class ToppingResource(ModelResource):
    pizza = fields.ForeignKey(PizzaResource, 'pizza')

    class Meta:
        authentication = SessionAuthentication()
        queryset = Topping.objects.filter()

The according models are like this:

class Pizza(model):
    users = ManyToManyField(User)
    toppings = ManyToManyField(Topping)
    # other stuff

class Topping(Model):
    used_by = ManyToManyField(User)
    # other stuff

Now what I want to do is filter the toppings listed with pizza by the Topping.used_by field. I just found how to filter this field by request unrelated data.

How can I filter a relationship field of tastypie by request data?

回答1:

Finally I found the answer by stepping through the code of tastypie. It turned out, that the model field in the definition of the ToMany relation (topping_set here) can be set to a callable.

Inside the callable you get as only parameter the bundle of data used to dehydrate the resulting data. Inside this bundle is always the request and so the user instance I want to use to filter.

So what I did was changing this:

toppings = fields.ToManyField(
    'project.app.api.ToppingResource', 
    'topping_set'
)

to this:

toppings = fields.ToManyField(
    'project.app.api.ToppingResource', 
    lambda bundle: Topping.objects.filter(
        pizza=bundle.obj, 
        used_by=bundle.request.user
    )
)

and that is it!