# 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
Comments