Although configuring filtering in TastyPie is possible, it is limited to per-field filters, which are not enough for more complex filtering.
If your model implement custom manager methods for complex filters, exposing these methods as TastyPie Resource list endpoints is not an easy task.
The ModelResource subclass provided here does this, providing 3 ways of complex filtering: define querysets for filters directly in the Resource declaration use Model manager custom method * use QuerySet custom method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | # by Michal migajek Gajek
class NBResource(ModelResource):
class Meta:
abstract = True
# there are three options for specifying filters.
# it's either a dictionary of 'filter_name': queryset
# or a tuple of filter names
# in the second case, if the default_manager attribute is provided
# the filter name is assumed to be Manager method,
# otherwise it's assumed to be QuerySet method
default_manager = None
manager_filters = ()
def prepend_urls(self):
""" if there are allowed custom Manager methods, add special url for that"""
return [
url(r"^(?P<resource_name>%s)/filtered_list/(?P<filter>\w+)%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('dispatch_list_filtered'), name="api_dispatch_list_filtered"),
] if self._meta.manager_filters else []
def dispatch_list_filtered(self, request, **kwargs):
""" check if the provided filter name is valid, and - if so - proceed to the get_object_list """
mfilter = kwargs.pop('filter')
filters = self._meta.manager_filters
if (isinstance(filters, dict) and not mfilter in filters.keys()) or \
not mfilter in filters:
raise Exception('Invalid filter (%s) name provided' % filter)
request.custom_filter = mfilter
return self.dispatch_list(request)
def get_object_list(self, request):
""" applies custom filtering if the filter name was provided """
if hasattr(request, 'custom_filter'):
filters = self._meta.manager_filters
if isinstance(filters, dict):
# filter to apply is in fact a name of queryset specified in Resource
queryset = filters[request.custom_filter]._clone()
else:
# if there's a default_manager, filter is it's method
# otherwise we assume filter is a method of default QuerySet
manager_or_queryset = self._meta.default_manager or super(NBResource, self).get_object_list(request)
method = getattr(manager_or_queryset, request.custom_filter)
if not method:
raise Exception('Manager or QuerySet does not have method named %s' % request.custom_filter)
#FIXME: very, very ugly trick...
kwargs = request.GET.dict()
if 'format' in kwargs.keys():
kwargs = deepcopy(kwargs)
kwargs.pop('format')
queryset = method(**kwargs)
else:
queryset = super(NBResource, self).get_object_list(request)
return queryset
#### example usage
# scenario one - simple - define filters as querysets directly in the ModelResource
class FooResource(NBResource)
class Meta:
queryset = Foo.objects.all() #standard definition for TastyPie
manager_filters = {'active': Foo.objects.filter(active = True) }
# calling /api/foo/filtered_list/active
# will return only items with active = True attribute
# scenario two - complex filtering based on custom Manager's method
class FooManager(models.Manager)
def recent_active_items(some_parameter)
return filteredQuerySet
class Foo(models.Model)
...
objects = FooManager()
class FooResource(NBResource)
class Meta:
queryset = Foo.objects.all() #standard definition for TastyPie
manager_filters = ('recent_active_items',)
default_manager = Foo.objects
# calling /api/foo/filtered_list/recent_active_items?some_parameter=value
# will call FooManager's method with some_parameter as keyword argument
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Please login first before commenting.