Fixed #14878 -- Clarified the way verbose_name_plural is used in generic list views as a context variable. Thanks to diegueus9 for the report.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15133 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2011-01-03 13:15:58 +00:00
parent 2a5105ac15
commit a00e8d4e42
10 changed files with 61 additions and 13 deletions

View File

@ -2,6 +2,7 @@ import re
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.http import Http404
from django.utils.encoding import smart_str
from django.views.generic.base import TemplateResponseMixin, View
@ -79,8 +80,8 @@ class SingleObjectMixin(object):
if self.context_object_name:
return self.context_object_name
elif hasattr(obj, '_meta'):
return re.sub('[^a-zA-Z0-9]+', '_',
obj._meta.verbose_name.lower())
return smart_str(re.sub('[^a-zA-Z0-9]+', '_',
obj._meta.verbose_name.lower()))
else:
return None

View File

@ -1,9 +1,12 @@
import re
from django.core.paginator import Paginator, InvalidPage
from django.core.exceptions import ImproperlyConfigured
from django.http import Http404
from django.utils.encoding import smart_str
from django.views.generic.base import TemplateResponseMixin, View
class MultipleObjectMixin(object):
allow_empty = True
queryset = None
@ -76,7 +79,8 @@ class MultipleObjectMixin(object):
if self.context_object_name:
return self.context_object_name
elif hasattr(object_list, 'model'):
return smart_str(object_list.model._meta.verbose_name_plural)
return smart_str(re.sub('[^a-zA-Z0-9]+', '_',
object_list.model._meta.verbose_name_plural.lower()))
else:
return None

View File

@ -428,7 +428,7 @@ FormMixin
.. method:: get_form_kwargs()
Build the keyword arguments requried to instanciate an the form.
The ``initial`` argument is set to :meth:`.get_initial`. If the
request is a ``POST`` or ``PUT``, the request data (``request.POST``
and ``request.FILES``) will also be provided.

View File

@ -206,14 +206,23 @@ their attributes or methods.
Making "friendly" template contexts
-----------------------------------
You might have noticed that our sample publisher list template stores all the
publishers in a variable named ``object_list``. While this works just fine, it
isn't all that "friendly" to template authors: they have to "just know" that
they're dealing with publishers here. A more obvious name for that variable
would be ``publisher_list``.
You might have noticed that our sample publisher list template stores
all the publishers in a variable named ``object_list``. While this
works just fine, it isn't all that "friendly" to template authors:
they have to "just know" that they're dealing with publishers here.
We can change the name of that variable easily with the ``context_object_name``
attribute - here, we'll override it in the URLconf, since it's a simple change:
Well, if you're dealing with a Django object, this is already done for
you. When you are dealing with an object or queryset, Django is able
to populate the context using the verbose name (or the plural verbose
name, in the case of a list of objects) of the object being displayed.
This is provided in addition to the default ``object_list`` entry, but
contains exactly the same data.
If the verbose name (or plural verbose name) still isn't a good match,
you can manually set the name of the context variable. The
``context_object_name`` attribute on a generic view specifies the
context variable to use. In this example, we'll override it in the
URLconf, since it's a simple change:
.. parsed-literal::

View File

@ -1,7 +1,7 @@
from django.core.exceptions import ImproperlyConfigured
from django.test import TestCase
from regressiontests.generic_views.models import Author, Page
from regressiontests.generic_views.models import Artist, Author, Page
class DetailViewTest(TestCase):
@ -28,6 +28,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_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.assertTemplateUsed(res, 'generic_views/artist_detail.html')
def test_template_name(self):
res = self.client.get('/detail/author/1/template_name/')
self.assertEqual(res.status_code, 200)

View File

@ -1,4 +1,11 @@
[
{
"model": "generic_views.artist",
"pk": 1,
"fields": {
"name": "Rene Magritte"
}
},
{
"model": "generic_views.author",
"pk": 1,

View File

@ -1,7 +1,7 @@
from django.core.exceptions import ImproperlyConfigured
from django.test import TestCase
from regressiontests.generic_views.models import Author
from regressiontests.generic_views.models import Author, Artist
from regressiontests.generic_views.views import CustomPaginator
class ListViewTests(TestCase):
@ -106,6 +106,16 @@ class ListViewTests(TestCase):
self.assertEqual(res.status_code, 200)
self.assertEqual(len(res.context['object_list']), 1)
def test_verbose_name(self):
res = self.client.get('/list/artists/')
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.assertIsNone(res.context['paginator'])
self.assertIsNone(res.context['page_obj'])
self.assertFalse(res.context['is_paginated'])
def test_allow_empty_false(self):
res = self.client.get('/list/authors/notempty/')
self.assertEqual(res.status_code, 200)

View File

@ -5,6 +5,8 @@ class Artist(models.Model):
class Meta:
ordering = ['name']
verbose_name = 'professional artist'
verbose_name_plural = 'professional artists'
def __unicode__(self):
return self.name

View File

@ -100,6 +100,9 @@ urlpatterns = patterns('',
views.DictList.as_view()),
(r'^list/dict/paginated/$',
views.DictList.as_view(paginate_by=1)),
url(r'^list/artists/$',
views.ArtistList.as_view(),
name="artists_list"),
url(r'^list/authors/$',
views.AuthorList.as_view(),
name="authors_list"),

View File

@ -47,6 +47,11 @@ class DictList(generic.ListView):
template_name = 'generic_views/list.html'
class ArtistList(generic.ListView):
template_name = 'generic_views/list.html'
queryset = Artist.objects.all()
class AuthorList(generic.ListView):
queryset = Author.objects.all()