aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Christie2013-04-09 19:01:01 +0100
committerTom Christie2013-04-09 19:01:01 +0100
commitdc45bc7bfad64a17f3e5ed0f5a487bccc379aac2 (patch)
treef5e4bfcdc01e3a89898be2e88e9cd86bb6bb5069
parent099163f81f9d89746de50f3aed2955ead54dba4e (diff)
downloaddjango-rest-framework-dc45bc7bfad64a17f3e5ed0f5a487bccc379aac2.tar.bz2
Add lookup_kwarg
-rw-r--r--rest_framework/generics.py18
-rw-r--r--rest_framework/tests/filterset.py6
2 files changed, 15 insertions, 9 deletions
diff --git a/rest_framework/generics.py b/rest_framework/generics.py
index af3b69da..d4a50dcd 100644
--- a/rest_framework/generics.py
+++ b/rest_framework/generics.py
@@ -26,6 +26,7 @@ class GenericAPIView(views.APIView):
pagination_serializer_class = api_settings.DEFAULT_PAGINATION_SERIALIZER_CLASS
allow_empty = True
page_kwarg = 'page'
+ lookup_kwarg = 'pk'
# Pending deprecation
model = None
@@ -167,23 +168,26 @@ class GenericAPIView(views.APIView):
By default this requires `self.queryset` and a `pk` or `slug` argument
in the URLconf, but subclasses can override this to return any object.
"""
- # Use a custom queryset if provided; this is required for subclasses
- # like DateDetailView
+ # Determine the base queryset to use.
if queryset is None:
queryset = self.get_queryset()
- # Next, try looking up by primary key.
+
+ # Perform the lookup filtering.
pk = self.kwargs.get(self.pk_url_kwarg, None)
slug = self.kwargs.get(self.slug_url_kwarg, None)
- if pk is not None:
+ lookup = self.kwargs.get(self.lookup_kwarg, None)
+
+ if lookup is not None:
+ queryset = queryset.filter(**{self.lookup_kwarg: lookup})
+ elif pk is not None:
queryset = queryset.filter(pk=pk)
- # Next, try looking up by slug.
elif slug is not None:
queryset = queryset.filter(**{self.slug_field: slug})
- # If none of those are defined, it's an error.
else:
raise AttributeError("Generic detail view %s must be called with "
"either an object pk or a slug."
% self.__class__.__name__)
+
try:
# Get the single item from the filtered queryset
obj = queryset.get()
@@ -191,7 +195,9 @@ class GenericAPIView(views.APIView):
raise Http404(_("No %(verbose_name)s found matching the query") %
{'verbose_name': queryset.model._meta.verbose_name})
+ # May raise a permission denied
self.check_object_permissions(self.request, obj)
+
return obj
diff --git a/rest_framework/tests/filterset.py b/rest_framework/tests/filterset.py
index 1a71558c..1e53a5cd 100644
--- a/rest_framework/tests/filterset.py
+++ b/rest_framework/tests/filterset.py
@@ -61,7 +61,7 @@ if django_filters:
class CommonFilteringTestCase(TestCase):
def _serialize_object(self, obj):
return {'id': obj.id, 'text': obj.text, 'decimal': obj.decimal, 'date': obj.date}
-
+
def setUp(self):
"""
Create 10 FilterableItem instances.
@@ -190,7 +190,7 @@ class IntegrationTestDetailFiltering(CommonFilteringTestCase):
Integration tests for filtered detail views.
"""
urls = 'rest_framework.tests.filterset'
-
+
def _get_url(self, item):
return reverse('detail-view', kwargs=dict(pk=item.pk))
@@ -221,7 +221,7 @@ class IntegrationTestDetailFiltering(CommonFilteringTestCase):
response = self.client.get('{url}?decimal={param}'.format(url=self._get_url(low_item), param=search_decimal))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, low_item_data)
-
+
# Tests that multiple filters works.
search_decimal = Decimal('5.25')
search_date = datetime.date(2012, 10, 2)