Search code examples
pythondjangotastypie

Tastypie: Filtering by ToManyField


I have the following resources:

class SpecResource(ModelResource):
    results = fields.ToManyField('(...).ResultResource', 'result_set', full=True)
    (...)

class ResultResource(ModelResource):
    number = fields.IntegerField()
    spec = fields.ForeignKey('(...).SpecResource', 'spec')
    (...)

so that when I look at a spec JSON it includes a list of the results that have a ForeignKey to that spec. Now I'd like to filter the results that show up when I look at a spec JSON, and I'd like to be able to filter through the URL in the way that you'd filter a list of specs by a field of the specs. Is that possible?

To illustrate further, I'd like to go to "/api/spec/1/?number=5" and get the same JSON that I'd get if I went to "/api/spec/1/" except that the results field only contains those results that have number = 5.

Is this possible within tastypie's framework?


Solution

  • It's been a while since you posted here, but you may find a piece of solution in the answer @kroolik gave me in a similar situation, to build a filter on a 'nested' ToManyField-related resource: https://stackoverflow.com/a/20035610/1387495

    Here is the main idea:

    You can extend your attribute argument you've passed to the results field with a full-scale function and reuse the ResultResource. The res.obj_get_list handles building and applying filters as defined per your ResultResource. You just need to filter it further on parent_id.

    In the code:

    class SpecResource(ModelResource):
        results = fields.ToManyField('(...).ResultResource', attribute=lambda bundle: filter_result_items(bundle), full=True)
    

    with

    def filter_result_items(bundle):
        res = ResultResource()
        new_bundle = Bundle(request=bundle.request)
        objs = res.obj_get_list(new_bundle)
        return objs.filter(parent_id=bundle.obj.pk)
    

    Once again, thank @kroolik, who showed me this trick.