Kaydet (Commit) 06b22963 authored tarafından Russell Keith-Magee's avatar Russell Keith-Magee

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

Fixed #15272 -- Altered generic views to use the guaranteed untranslated 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
üst a26034ff
......@@ -80,8 +80,7 @@ class SingleObjectMixin(object):
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
......
......@@ -76,8 +76,7 @@ class MultipleObjectMixin(object):
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
......
......@@ -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)
......
......@@ -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
------------------------------------------
......
......@@ -92,7 +92,7 @@ class YearArchiveViewTests(TestCase):
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 @@ class YearArchiveViewTests(TestCase):
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 @@ class YearArchiveViewTests(TestCase):
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 @@ class MonthArchiveViewTests(TestCase):
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 @@ class MonthArchiveViewTests(TestCase):
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 @@ class MonthArchiveViewTests(TestCase):
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 @@ class WeekArchiveViewTests(TestCase):
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 @@ class WeekArchiveViewTests(TestCase):
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 @@ class WeekArchiveViewTests(TestCase):
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 @@ class DayArchiveViewTests(TestCase):
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 @@ class DayArchiveViewTests(TestCase):
# 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 @@ class DayArchiveViewTests(TestCase):
# 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
......
......@@ -32,7 +32,7 @@ class DetailViewTest(TestCase):
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):
......
......@@ -19,7 +19,7 @@ class ListViewTests(TestCase):
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 @@ class ListViewTests(TestCase):
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 @@ class ListViewTests(TestCase):
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 @@ class ListViewTests(TestCase):
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 @@ class ListViewTests(TestCase):
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 @@ class ListViewTests(TestCase):
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 @@ class ListViewTests(TestCase):
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 @@ class ListViewTests(TestCase):
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):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment