From 2ccfb6d5c2ffb13ae3cb11a058ff574ab115518c Mon Sep 17 00:00:00 2001 From: Jannis Leidel Date: Fri, 29 Jul 2011 09:41:00 +0000 Subject: [PATCH] Fixed #16101 -- Added parameters to SingleObjectMixin to override the name of the URL keyword arguments used for pk and slug. Thanks, Andrew Ingram and Julien Phalip. git-svn-id: http://code.djangoproject.com/svn/django/trunk@16569 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/views/generic/detail.py | 6 +++-- docs/ref/class-based-views.txt | 23 +++++++++++++++---- docs/releases/1.4.txt | 10 ++++++++ tests/regressiontests/generic_views/detail.py | 14 +++++++++++ tests/regressiontests/generic_views/urls.py | 4 ++++ 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/django/views/generic/detail.py b/django/views/generic/detail.py index 16e2c4844d..ab215733b5 100644 --- a/django/views/generic/detail.py +++ b/django/views/generic/detail.py @@ -13,6 +13,8 @@ class SingleObjectMixin(object): queryset = None slug_field = 'slug' context_object_name = None + slug_url_kwarg = 'slug' + pk_url_kwarg = 'pk' def get_object(self, queryset=None): """ @@ -27,8 +29,8 @@ class SingleObjectMixin(object): queryset = self.get_queryset() # Next, try looking up by primary key. - pk = self.kwargs.get('pk', None) - slug = self.kwargs.get('slug', None) + pk = self.kwargs.get(self.pk_url_kwarg, None) + slug = self.kwargs.get(self.slug_url_kwarg, None) if pk is not None: queryset = queryset.filter(pk=pk) diff --git a/docs/ref/class-based-views.txt b/docs/ref/class-based-views.txt index 3448bbd6d7..2676c2cefc 100644 --- a/docs/ref/class-based-views.txt +++ b/docs/ref/class-based-views.txt @@ -136,6 +136,20 @@ SingleObjectMixin The name of the field on the model that contains the slug. By default, ``slug_field`` is ``'slug'``. + .. attribute:: slug_url_kwarg + + .. versionadded:: 1.4 + + The name of the URLConf keyword argument that contains the slug. By + default, ``slug_url_kwarg`` is ``'slug'``. + + .. attribute:: pk_url_kwarg + + .. versionadded:: 1.4 + + The name of the URLConf keyword argument that contains the primary key. + By default, ``pk_url_kwarg`` is ``'pk'``. + .. attribute:: context_object_name Designates the name of the variable to use in the context. @@ -146,10 +160,11 @@ SingleObjectMixin ``queryset`` is provided, that queryset will be used as the source of objects; otherwise, :meth:`~SingleObjectMixin.get_queryset` will be used. - :meth:`~SingleObjectMixin.get_object` looks for a ``pk`` - argument in the arguments to the view; if ``pk`` is found, - this method performs a primary-key based lookup using that - value. If no ``pk`` argument is found, it looks for a ``slug`` + ``get_object()`` looks for a + :attr:`SingleObjectMixin.pk_url_kwarg` argument in the arguments + to the view; if this argument is found, this method performs a + primary-key based lookup using that value. If this argument is not + found, it looks for a :attr:`SingleObjectMixin.slug_url_kwarg` argument, and performs a slug lookup using the :attr:`SingleObjectMixin.slug_field`. diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt index 43c9ae25c5..2723b42195 100644 --- a/docs/releases/1.4.txt +++ b/docs/releases/1.4.txt @@ -153,6 +153,16 @@ number of characters. Truncated strings end with a translatable ellipsis sequence ("..."). See the :tfilter:`truncatechars docs ` for more details. +Customizable ``SingleObjectMixin`` URLConf kwargs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Two new attributes, +:attr:`pk_url_kwarg` and +:attr:`slug_url_kwarg`, +have been added to :class:`django.views.generic.detail.SingleObjectMixin` to +enable the customization of URLConf keyword arguments used for single +object generic views. + CSRF improvements ~~~~~~~~~~~~~~~~~ diff --git a/tests/regressiontests/generic_views/detail.py b/tests/regressiontests/generic_views/detail.py index e8f2050fe2..c1cc2fbddb 100644 --- a/tests/regressiontests/generic_views/detail.py +++ b/tests/regressiontests/generic_views/detail.py @@ -21,6 +21,13 @@ class DetailViewTest(TestCase): self.assertEqual(res.context['author'], Author.objects.get(pk=1)) self.assertTemplateUsed(res, 'generic_views/author_detail.html') + def test_detail_by_custom_pk(self): + res = self.client.get('/detail/author/bycustompk/1/') + self.assertEqual(res.status_code, 200) + self.assertEqual(res.context['object'], Author.objects.get(pk=1)) + self.assertEqual(res.context['author'], Author.objects.get(pk=1)) + self.assertTemplateUsed(res, 'generic_views/author_detail.html') + def test_detail_by_slug(self): res = self.client.get('/detail/author/byslug/scott-rosenberg/') self.assertEqual(res.status_code, 200) @@ -28,6 +35,13 @@ class DetailViewTest(TestCase): self.assertEqual(res.context['author'], Author.objects.get(slug='scott-rosenberg')) self.assertTemplateUsed(res, 'generic_views/author_detail.html') + def test_detail_by_custom_slug(self): + res = self.client.get('/detail/author/bycustomslug/scott-rosenberg/') + self.assertEqual(res.status_code, 200) + self.assertEqual(res.context['object'], Author.objects.get(slug='scott-rosenberg')) + self.assertEqual(res.context['author'], Author.objects.get(slug='scott-rosenberg')) + self.assertTemplateUsed(res, 'generic_views/author_detail.html') + def test_verbose_name(self): res = self.client.get('/detail/artist/1/') self.assertEqual(res.status_code, 200) diff --git a/tests/regressiontests/generic_views/urls.py b/tests/regressiontests/generic_views/urls.py index 067c1f687a..0f844e0243 100644 --- a/tests/regressiontests/generic_views/urls.py +++ b/tests/regressiontests/generic_views/urls.py @@ -30,8 +30,12 @@ urlpatterns = patterns('', url(r'^detail/author/(?P\d+)/$', views.AuthorDetail.as_view(), name="author_detail"), + (r'^detail/author/bycustompk/(?P\d+)/$', + views.AuthorDetail.as_view(pk_url_kwarg='foo')), (r'^detail/author/byslug/(?P[\w-]+)/$', views.AuthorDetail.as_view()), + (r'^detail/author/bycustomslug/(?P[\w-]+)/$', + views.AuthorDetail.as_view(slug_url_kwarg='foo')), (r'^detail/author/(?P\d+)/template_name_suffix/$', views.AuthorDetail.as_view(template_name_suffix='_view')), (r'^detail/author/(?P\d+)/template_name/$',