Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #15272 -- Altered generic views to use the guaranteed untransla…

…ted object_name, rather than the possibly translated verbose_name(_plural) for default context objects. Thanks to szczav for the report and patch.

This is BACKWARDS INCOMPATIBLE for anyone relying on the default context object names for class-based Detail and List views. To migrate, either update your templates to use the new default names, or add a context_object_name argument to your generic views.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15531 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 06b22963eae4751d3d5f9616ba24b0f33b8158b0 1 parent a26034f
@freakboy3742 freakboy3742 authored
View
3  django/views/generic/detail.py
@@ -80,8 +80,7 @@ def get_context_object_name(self, obj):
if self.context_object_name:
return self.context_object_name
elif hasattr(obj, '_meta'):
- return smart_str(re.sub('[^a-zA-Z0-9]+', '_',
- obj._meta.verbose_name.lower()))
+ return smart_str(obj._meta.object_name.lower())
else:
return None
View
3  django/views/generic/list.py
@@ -76,8 +76,7 @@ def get_context_object_name(self, object_list):
if self.context_object_name:
return self.context_object_name
elif hasattr(object_list, 'model'):
- return smart_str(re.sub('[^a-zA-Z0-9]+', '_',
- object_list.model._meta.verbose_name_plural.lower()))
+ return smart_str('%s_list' % object_list.model._meta.object_name.lower())
else:
return None
View
22 docs/ref/class-based-views.txt
@@ -162,14 +162,14 @@ SingleObjectMixin
it constructs a :class:`QuerySet` by calling the `all()` method on the
:attr:`~SingleObjectMixin.model` attribute's default manager.
- .. method:: get_context_object_name(object_list)
+ .. method:: get_context_object_name(obj)
Return the context variable name that will be used to contain the
- list of data that this view is manipulating. If ``object_list`` is a
- :class:`QuerySet` of Django objects and
+ data that this view is manipulating. If
:attr:`~SingleObjectMixin.context_object_name` is not set, the context
- name will be constructed from the verbose plural name of the model that
- the queryset is composed from.
+ name will be constructed from the ``object_name`` of the model that
+ the queryset is composed from. For example, the model ``Article``
+ would have context object named ``'article'``.
.. method:: get_context_data(**kwargs)
@@ -333,10 +333,14 @@ MultipleObjectMixin
.. method:: get_context_object_name(object_list)
- Return the context variable name that will be used to contain the list
- of data that this view is manipulating. If object_list is a queryset of
- Django objects, the context name will be verbose plural name of the
- model that the queryset is composed from.
+ Return the context variable name that will be used to contain
+ the list of data that this view is manipulating. If
+ ``object_list`` is a queryset of Django objects and
+ :attr:`~MultipleObjectMixin.context_object_name` is not set,
+ the context name will be the ``object_name`` of the model that
+ the queryset is composed from, with postfix ``'_list'``
+ appended. For example, the model ``Article`` would have a
+ context object named ``article_list``.
.. method:: get_context_data(**kwargs)
View
3  docs/topics/generic-views-migration.txt
@@ -72,7 +72,8 @@ The ``_list`` suffix on list views
In a function-based :class:`ListView`, the ``template_object_name``
was appended with the suffix ``'_list'`` to yield the final context
variable name. In a class-based ``ListView``, the
-``context_object_name`` is used verbatim.
+``context_object_name`` is used verbatim. The ``'_list'`` suffix
+is only applied when generating a default context object name.
The context data for ``object_list`` views
------------------------------------------
View
24 tests/regressiontests/generic_views/dates.py
@@ -92,7 +92,7 @@ def test_year_view_make_object_list(self):
res = self.client.get('/dates/books/2006/make_object_list/')
self.assertEqual(res.status_code, 200)
self.assertEqual(list(res.context['date_list']), [datetime.datetime(2006, 5, 1)])
- self.assertEqual(list(res.context['books']), list(Book.objects.filter(pubdate__year=2006)))
+ self.assertEqual(list(res.context['book_list']), list(Book.objects.filter(pubdate__year=2006)))
self.assertEqual(list(res.context['object_list']), list(Book.objects.filter(pubdate__year=2006)))
self.assertTemplateUsed(res, 'generic_views/book_archive_year.html')
@@ -102,7 +102,7 @@ def test_year_view_empty(self):
res = self.client.get('/dates/books/1999/allow_empty/')
self.assertEqual(res.status_code, 200)
self.assertEqual(list(res.context['date_list']), [])
- self.assertEqual(list(res.context['books']), [])
+ self.assertEqual(list(res.context['book_list']), [])
def test_year_view_allow_future(self):
# Create a new book in the future
@@ -113,7 +113,7 @@ def test_year_view_allow_future(self):
res = self.client.get('/dates/books/%s/allow_empty/' % year)
self.assertEqual(res.status_code, 200)
- self.assertEqual(list(res.context['books']), [])
+ self.assertEqual(list(res.context['book_list']), [])
res = self.client.get('/dates/books/%s/allow_future/' % year)
self.assertEqual(res.status_code, 200)
@@ -132,7 +132,7 @@ def test_month_view(self):
self.assertEqual(res.status_code, 200)
self.assertTemplateUsed(res, 'generic_views/book_archive_month.html')
self.assertEqual(list(res.context['date_list']), [datetime.datetime(2008, 10, 1)])
- self.assertEqual(list(res.context['books']),
+ self.assertEqual(list(res.context['book_list']),
list(Book.objects.filter(pubdate=datetime.date(2008, 10, 1))))
self.assertEqual(res.context['month'], datetime.date(2008, 10, 1))
@@ -149,7 +149,7 @@ def test_month_view_allow_empty(self):
res = self.client.get('/dates/books/2000/jan/allow_empty/')
self.assertEqual(res.status_code, 200)
self.assertEqual(list(res.context['date_list']), [])
- self.assertEqual(list(res.context['books']), [])
+ self.assertEqual(list(res.context['book_list']), [])
self.assertEqual(res.context['month'], datetime.date(2000, 1, 1))
# Since it's allow empty, next/prev are allowed to be empty months (#7164)
@@ -175,7 +175,7 @@ def test_month_view_allow_future(self):
res = self.client.get('/dates/books/%s/allow_future/' % urlbit)
self.assertEqual(res.status_code, 200)
self.assertEqual(res.context['date_list'][0].date(), b.pubdate)
- self.assertEqual(list(res.context['books']), [b])
+ self.assertEqual(list(res.context['book_list']), [b])
self.assertEqual(res.context['month'], future)
# Since it's allow_future but not allow_empty, next/prev are not
@@ -229,7 +229,7 @@ def test_week_view(self):
res = self.client.get('/dates/books/2008/week/39/')
self.assertEqual(res.status_code, 200)
self.assertTemplateUsed(res, 'generic_views/book_archive_week.html')
- self.assertEqual(res.context['books'][0], Book.objects.get(pubdate=datetime.date(2008, 10, 1)))
+ self.assertEqual(res.context['book_list'][0], Book.objects.get(pubdate=datetime.date(2008, 10, 1)))
self.assertEqual(res.context['week'], datetime.date(2008, 9, 28))
def test_week_view_allow_empty(self):
@@ -238,7 +238,7 @@ def test_week_view_allow_empty(self):
res = self.client.get('/dates/books/2008/week/12/allow_empty/')
self.assertEqual(res.status_code, 200)
- self.assertEqual(list(res.context['books']), [])
+ self.assertEqual(list(res.context['book_list']), [])
def test_week_view_allow_future(self):
future = datetime.date(datetime.date.today().year + 1, 1, 1)
@@ -249,7 +249,7 @@ def test_week_view_allow_future(self):
res = self.client.get('/dates/books/%s/week/1/allow_future/' % future.year)
self.assertEqual(res.status_code, 200)
- self.assertEqual(list(res.context['books']), [b])
+ self.assertEqual(list(res.context['book_list']), [b])
def test_week_view_invalid_pattern(self):
res = self.client.get('/dates/books/2007/week/no_week/')
@@ -273,7 +273,7 @@ def test_day_view(self):
res = self.client.get('/dates/books/2008/oct/01/')
self.assertEqual(res.status_code, 200)
self.assertTemplateUsed(res, 'generic_views/book_archive_day.html')
- self.assertEqual(list(res.context['books']),
+ self.assertEqual(list(res.context['book_list']),
list(Book.objects.filter(pubdate=datetime.date(2008, 10, 1))))
self.assertEqual(res.context['day'], datetime.date(2008, 10, 1))
@@ -289,7 +289,7 @@ def test_day_view_allow_empty(self):
# allow_empty = True, empty month
res = self.client.get('/dates/books/2000/jan/1/allow_empty/')
self.assertEqual(res.status_code, 200)
- self.assertEqual(list(res.context['books']), [])
+ self.assertEqual(list(res.context['book_list']), [])
self.assertEqual(res.context['day'], datetime.date(2000, 1, 1))
# Since it's allow empty, next/prev are allowed to be empty months (#7164)
@@ -314,7 +314,7 @@ def test_day_view_allow_future(self):
# allow_future = True, valid future month
res = self.client.get('/dates/books/%s/allow_future/' % urlbit)
self.assertEqual(res.status_code, 200)
- self.assertEqual(list(res.context['books']), [b])
+ self.assertEqual(list(res.context['book_list']), [b])
self.assertEqual(res.context['day'], future)
# allow_future but not allow_empty, next/prev amust be valid
View
2  tests/regressiontests/generic_views/detail.py
@@ -32,7 +32,7 @@ def test_verbose_name(self):
res = self.client.get('/detail/artist/1/')
self.assertEqual(res.status_code, 200)
self.assertEqual(res.context['object'], Artist.objects.get(pk=1))
- self.assertEqual(res.context['professional_artist'], Artist.objects.get(pk=1))
+ self.assertEqual(res.context['artist'], Artist.objects.get(pk=1))
self.assertTemplateUsed(res, 'generic_views/artist_detail.html')
def test_template_name(self):
View
28 tests/regressiontests/generic_views/list.py
@@ -19,7 +19,7 @@ def test_queryset(self):
self.assertEqual(res.status_code, 200)
self.assertTemplateUsed(res, 'generic_views/author_list.html')
self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
- self.assertIs(res.context['authors'], res.context['object_list'])
+ self.assertIs(res.context['author_list'], res.context['object_list'])
self.assertIsNone(res.context['paginator'])
self.assertIsNone(res.context['page_obj'])
self.assertFalse(res.context['is_paginated'])
@@ -30,12 +30,12 @@ def test_paginated_queryset(self):
self.assertEqual(res.status_code, 200)
self.assertTemplateUsed(res, 'generic_views/author_list.html')
self.assertEqual(len(res.context['object_list']), 30)
- self.assertIs(res.context['authors'], res.context['object_list'])
+ self.assertIs(res.context['author_list'], res.context['object_list'])
self.assertTrue(res.context['is_paginated'])
self.assertEqual(res.context['page_obj'].number, 1)
self.assertEqual(res.context['paginator'].num_pages, 4)
- self.assertEqual(res.context['authors'][0].name, 'Author 00')
- self.assertEqual(list(res.context['authors'])[-1].name, 'Author 29')
+ self.assertEqual(res.context['author_list'][0].name, 'Author 00')
+ self.assertEqual(list(res.context['author_list'])[-1].name, 'Author 29')
def test_paginated_queryset_shortdata(self):
# Test that short datasets ALSO result in a paginated view.
@@ -43,7 +43,7 @@ def test_paginated_queryset_shortdata(self):
self.assertEqual(res.status_code, 200)
self.assertTemplateUsed(res, 'generic_views/author_list.html')
self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
- self.assertIs(res.context['authors'], res.context['object_list'])
+ self.assertIs(res.context['author_list'], res.context['object_list'])
self.assertEqual(res.context['page_obj'].number, 1)
self.assertEqual(res.context['paginator'].num_pages, 1)
self.assertTrue(res.context['is_paginated'])
@@ -54,8 +54,8 @@ def test_paginated_get_page_by_query_string(self):
self.assertEqual(res.status_code, 200)
self.assertTemplateUsed(res, 'generic_views/author_list.html')
self.assertEqual(len(res.context['object_list']), 30)
- self.assertIs(res.context['authors'], res.context['object_list'])
- self.assertEqual(res.context['authors'][0].name, 'Author 30')
+ self.assertIs(res.context['author_list'], res.context['object_list'])
+ self.assertEqual(res.context['author_list'][0].name, 'Author 30')
self.assertEqual(res.context['page_obj'].number, 2)
def test_paginated_get_last_page_by_query_string(self):
@@ -63,8 +63,8 @@ def test_paginated_get_last_page_by_query_string(self):
res = self.client.get('/list/authors/paginated/', {'page': 'last'})
self.assertEqual(res.status_code, 200)
self.assertEqual(len(res.context['object_list']), 10)
- self.assertIs(res.context['authors'], res.context['object_list'])
- self.assertEqual(res.context['authors'][0].name, 'Author 90')
+ self.assertIs(res.context['author_list'], res.context['object_list'])
+ self.assertEqual(res.context['author_list'][0].name, 'Author 90')
self.assertEqual(res.context['page_obj'].number, 4)
def test_paginated_get_page_by_urlvar(self):
@@ -73,8 +73,8 @@ def test_paginated_get_page_by_urlvar(self):
self.assertEqual(res.status_code, 200)
self.assertTemplateUsed(res, 'generic_views/author_list.html')
self.assertEqual(len(res.context['object_list']), 30)
- self.assertIs(res.context['authors'], res.context['object_list'])
- self.assertEqual(res.context['authors'][0].name, 'Author 60')
+ self.assertIs(res.context['author_list'], res.context['object_list'])
+ self.assertEqual(res.context['author_list'][0].name, 'Author 60')
self.assertEqual(res.context['page_obj'].number, 3)
def test_paginated_page_out_of_range(self):
@@ -112,7 +112,7 @@ def test_verbose_name(self):
self.assertEqual(res.status_code, 200)
self.assertTemplateUsed(res, 'generic_views/list.html')
self.assertEqual(list(res.context['object_list']), list(Artist.objects.all()))
- self.assertIs(res.context['professional_artists'], res.context['object_list'])
+ self.assertIs(res.context['artist_list'], res.context['object_list'])
self.assertIsNone(res.context['paginator'])
self.assertIsNone(res.context['page_obj'])
self.assertFalse(res.context['is_paginated'])
@@ -128,14 +128,14 @@ def test_template_name(self):
res = self.client.get('/list/authors/template_name/')
self.assertEqual(res.status_code, 200)
self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
- self.assertIs(res.context['authors'], res.context['object_list'])
+ self.assertIs(res.context['author_list'], res.context['object_list'])
self.assertTemplateUsed(res, 'generic_views/list.html')
def test_template_name_suffix(self):
res = self.client.get('/list/authors/template_name_suffix/')
self.assertEqual(res.status_code, 200)
self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
- self.assertIs(res.context['authors'], res.context['object_list'])
+ self.assertIs(res.context['author_list'], res.context['object_list'])
self.assertTemplateUsed(res, 'generic_views/author_objects.html')
def test_context_object_name(self):
Please sign in to comment.
Something went wrong with that request. Please try again.