From 9141171ba0966f745a45217fdc0ec6a0a62ae728 Mon Sep 17 00:00:00 2001 From: Dev Jones Date: Sat, 18 Feb 2012 22:32:27 -0500 Subject: [PATCH 1/3] Added support for filtering via query parameters --- djangorestframework/mixins.py | 50 ++++++++++++++++++++++++++++++++++- djangorestframework/views.py | 10 +++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/djangorestframework/mixins.py b/djangorestframework/mixins.py index cb0b913a7..f807374d8 100644 --- a/djangorestframework/mixins.py +++ b/djangorestframework/mixins.py @@ -33,6 +33,8 @@ __all__ = ( 'UpdateModelMixin', 'DeleteModelMixin', 'ListModelMixin' + 'FilterModelMixin' + ) @@ -182,7 +184,7 @@ class RequestMixin(object): return parser.parse(stream) raise ErrorResponse(status.HTTP_415_UNSUPPORTED_MEDIA_TYPE, - {'error': 'Unsupported media type in request \'%s\'.' % + {'error': 'Unsupported media type in request \'%s\'.' % content_type}) @property @@ -659,6 +661,52 @@ class ListModelMixin(ModelMixin): return queryset +class FilterModelMixin(ModelMixin): + """ + Behavior to list a set of `model` instances on GET requests + Also Enables a filter via the url query parameters + + Example: Each of the following requests are valid + 1) http://www.example.com/?color=blue + 2) http://www.example.com/shirts/?color=blue + """ + + + def get(self, request, *args, **kwargs): + queryset = self.get_queryset() + ordering = self.get_ordering() + + + filter_data = dict(request.GET.items()) + + # Get the fields for the resource + model = self.resource.model + fields = model._meta.fields + + # Iterate over fields and get the field names + fieldnames = [field.name for field in fields] + + + # Initialize query object + filter_query = Q() + + # Check to ensure that each filter key is a valid field in the model + for filter_key,value in filter_data.iteritems(): + if filter_key in fieldnames: + new_filter = {filter_key:value} + new_query = Q(**new_filter) + + filter_query = filter_query & new_query + + + + + queryset = queryset.filter(self.build_query(**kwargs)).filter(filter_query) + if ordering: + queryset = queryset.order_by(*ordering) + + return queryset + ########## Pagination Mixins ########## class PaginatorMixin(object): diff --git a/djangorestframework/views.py b/djangorestframework/views.py index 32d2437c1..518041d5a 100644 --- a/djangorestframework/views.py +++ b/djangorestframework/views.py @@ -24,6 +24,7 @@ __all__ = ( 'InstanceModelView', 'ListModelView', 'ListOrCreateModelView' + 'FilterOrCreateModelView' ) @@ -296,3 +297,12 @@ class ListOrCreateModelView(ListModelMixin, CreateModelMixin, ModelView): A view which provides default operations for list and create, against a model in the database. """ _suffix = 'List' + + + +class FilterOrCreateModelView(FilterModelMixin, CreateModelMixin, ModelView): + """ + A view which provides default operations for list and create, against a model in the database. + The view also enables filtering by query parameters + """ + _suffix = 'List' From 03951615e1d7aff97bca20b2a1498ace5474bfba Mon Sep 17 00:00:00 2001 From: Dev Jones Date: Sat, 18 Feb 2012 23:11:54 -0500 Subject: [PATCH 2/3] update accessible mixins/views --- djangorestframework/mixins.py | 4 ++-- djangorestframework/views.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/djangorestframework/mixins.py b/djangorestframework/mixins.py index f807374d8..0e91ae206 100644 --- a/djangorestframework/mixins.py +++ b/djangorestframework/mixins.py @@ -32,8 +32,8 @@ __all__ = ( 'CreateModelMixin', 'UpdateModelMixin', 'DeleteModelMixin', - 'ListModelMixin' - 'FilterModelMixin' + 'ListModelMixin', + 'FilterModelMixin', ) diff --git a/djangorestframework/views.py b/djangorestframework/views.py index 518041d5a..b6424b23c 100644 --- a/djangorestframework/views.py +++ b/djangorestframework/views.py @@ -23,7 +23,7 @@ __all__ = ( 'ModelView', 'InstanceModelView', 'ListModelView', - 'ListOrCreateModelView' + 'ListOrCreateModelView', 'FilterOrCreateModelView' ) From 63660c85f9e8cb04f37e4201683cf748040eb8f5 Mon Sep 17 00:00:00 2001 From: Dev Jones Date: Sun, 19 Feb 2012 00:30:00 -0500 Subject: [PATCH 3/3] removed support for Q obj --- djangorestframework/mixins.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/djangorestframework/mixins.py b/djangorestframework/mixins.py index 0e91ae206..d308561bd 100644 --- a/djangorestframework/mixins.py +++ b/djangorestframework/mixins.py @@ -35,6 +35,8 @@ __all__ = ( 'ListModelMixin', 'FilterModelMixin', + 'PaginatorMixin', + ) @@ -676,7 +678,6 @@ class FilterModelMixin(ModelMixin): queryset = self.get_queryset() ordering = self.get_ordering() - filter_data = dict(request.GET.items()) # Get the fields for the resource @@ -686,26 +687,28 @@ class FilterModelMixin(ModelMixin): # Iterate over fields and get the field names fieldnames = [field.name for field in fields] + # Fixed query parameters included in the url path. Ex: /resource/// + query_kwargs = self.get_query_kwargs(request, *args, **kwargs) - # Initialize query object - filter_query = Q() + # Dynamic query parameters from the url query. Ex: /resource/?color=blue + dynamic_query_kwargs = {} # Check to ensure that each filter key is a valid field in the model for filter_key,value in filter_data.iteritems(): if filter_key in fieldnames: - new_filter = {filter_key:value} - new_query = Q(**new_filter) - - filter_query = filter_query & new_query + dynamic_query_kwargs[filter_key] = value + # Combine the query kwargs from the fixed url path and the dynamic url query parameters + filtered_query_kwargs = dict(query_kwargs.items() + dynamic_query_kwargs.items()) + # Get a single query using the combined query kwargs + filtered_queryset = queryset.filter(**filtered_query_kwargs) - queryset = queryset.filter(self.build_query(**kwargs)).filter(filter_query) if ordering: - queryset = queryset.order_by(*ordering) + filtered_queryset = filtered_queryset.order_by(*ordering) - return queryset + return filtered_queryset ########## Pagination Mixins ##########