diff --git a/djangorestframework/mixins.py b/djangorestframework/mixins.py index f38277eb4..0b41aae82 100644 --- a/djangorestframework/mixins.py +++ b/djangorestframework/mixins.py @@ -32,7 +32,11 @@ __all__ = ( 'CreateModelMixin', 'UpdateModelMixin', 'DeleteModelMixin', - 'ListModelMixin' + 'ListModelMixin', + 'FilterModelMixin', + + 'PaginatorMixin', + ) @@ -182,7 +186,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 +663,53 @@ 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] + + # Fixed query parameters included in the url path. Ex: /resource/// + query_kwargs = self.get_query_kwargs(request, *args, **kwargs) + + # 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: + 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) + + if ordering: + filtered_queryset = filtered_queryset.order_by(*ordering) + + return filtered_queryset + ########## Pagination Mixins ########## class PaginatorMixin(object): diff --git a/djangorestframework/views.py b/djangorestframework/views.py index bcdb50391..fae176b98 100644 --- a/djangorestframework/views.py +++ b/djangorestframework/views.py @@ -23,7 +23,8 @@ __all__ = ( 'ModelView', 'InstanceModelView', 'ListModelView', - 'ListOrCreateModelView' + 'ListOrCreateModelView', + 'FilterOrCreateModelView' ) @@ -288,3 +289,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'