Browse Source

Fixed #16744 -- Class based view should have the view object in the context

Updated the most recent patch from @claudep to apply again and updated
the documentation location.
Marc Tamlyn 12 years ago
parent
commit
58683e9c82

+ 2 - 0
django/views/generic/base.py

@@ -18,6 +18,8 @@ class ContextMixin(object):
     """
 
     def get_context_data(self, **kwargs):
+        if 'view' not in kwargs:
+            kwargs['view'] = self
         return kwargs
 
 

+ 14 - 2
docs/ref/class-based-views/mixins-simple.txt

@@ -17,8 +17,20 @@ ContextMixin
 
     .. method:: get_context_data(**kwargs)
 
-        Returns a dictionary representing the template context. The
-        keyword arguments provided will make up the returned context.
+        Returns a dictionary representing the template context. The keyword
+        arguments provided will make up the returned context.
+
+        The template context of all class-based generic views include a
+        ``view`` variable that points to the ``View`` instance.
+
+        .. admonition:: Use ``alters_data`` where appropriate
+
+            Note that having the view instance in the template context may
+            expose potentially hazardous methods to template authors.  To
+            prevent methods like this from being called in the template, set
+            ``alters_data=True`` on those methods.  For more information, read
+            the documentation on :ref:`rendering a template context
+            <alters-data-description>`.
 
 TemplateResponseMixin
 ---------------------

+ 2 - 0
docs/ref/templates/api.txt

@@ -198,6 +198,8 @@ straight lookups. Here are some things to keep in mind:
 * A variable can only be called if it has no required arguments. Otherwise,
   the system will return an empty string.
 
+.. _alters-data-description:
+
 * Obviously, there can be side effects when calling some variables, and
   it'd be either foolish or a security hole to allow the template system
   to access them.

+ 6 - 0
docs/releases/1.5.txt

@@ -84,6 +84,12 @@ By passing ``False`` using this argument it is now possible to retreive the
 :class:`ContentType <django.contrib.contenttypes.models.ContentType>`
 associated with proxy models.
 
+New ``view`` variable in class-based views context
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In all :doc:`generic class-based views </topics/class-based-views/index>`
+(or any class-based view inheriting from ``ContextMixin``), the context dictionary
+contains a ``view`` variable that points to the ``View`` instance.
+
 Minor features
 ~~~~~~~~~~~~~~
 

+ 2 - 0
tests/regressiontests/generic_views/base.py

@@ -276,6 +276,7 @@ class TemplateViewTest(TestCase):
         response = self.client.get('/template/simple/bar/')
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.context['params'], {'foo': 'bar'})
+        self.assertTrue(isinstance(response.context['view'], View))
 
     def test_extra_template_params(self):
         """
@@ -285,6 +286,7 @@ class TemplateViewTest(TestCase):
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.context['params'], {'foo': 'bar'})
         self.assertEqual(response.context['key'], 'value')
+        self.assertTrue(isinstance(response.context['view'], View))
 
     def test_cached_views(self):
         """

+ 2 - 0
tests/regressiontests/generic_views/detail.py

@@ -2,6 +2,7 @@ from __future__ import absolute_import
 
 from django.core.exceptions import ImproperlyConfigured
 from django.test import TestCase
+from django.views.generic.base import View
 
 from .models import Artist, Author, Page
 
@@ -14,6 +15,7 @@ class DetailViewTest(TestCase):
         res = self.client.get('/detail/obj/')
         self.assertEqual(res.status_code, 200)
         self.assertEqual(res.context['object'], {'foo': 'bar'})
+        self.assertTrue(isinstance(res.context['view'], View))
         self.assertTemplateUsed(res, 'generic_views/detail.html')
 
     def test_detail_by_pk(self):

+ 5 - 0
tests/regressiontests/generic_views/edit.py

@@ -5,6 +5,7 @@ from django.core.urlresolvers import reverse
 from django import forms
 from django.test import TestCase
 from django.utils.unittest import expectedFailure
+from django.views.generic.base import View
 from django.views.generic.edit import FormMixin
 
 from . import views
@@ -31,6 +32,7 @@ class CreateViewTests(TestCase):
         res = self.client.get('/edit/authors/create/')
         self.assertEqual(res.status_code, 200)
         self.assertTrue(isinstance(res.context['form'], forms.ModelForm))
+        self.assertTrue(isinstance(res.context['view'], View))
         self.assertFalse('object' in res.context)
         self.assertFalse('author' in res.context)
         self.assertTemplateUsed(res, 'generic_views/author_form.html')
@@ -101,6 +103,7 @@ class CreateViewTests(TestCase):
         self.assertEqual(res.status_code, 302)
         self.assertRedirects(res, 'http://testserver/accounts/login/?next=/edit/authors/create/restricted/')
 
+
 class UpdateViewTests(TestCase):
     urls = 'regressiontests.generic_views.urls'
 
@@ -226,6 +229,7 @@ class UpdateViewTests(TestCase):
         res = self.client.get('/edit/author/update/')
         self.assertEqual(res.status_code, 200)
         self.assertTrue(isinstance(res.context['form'], forms.ModelForm))
+        self.assertTrue(isinstance(res.context['view'], View))
         self.assertEqual(res.context['object'], Author.objects.get(pk=a.pk))
         self.assertEqual(res.context['author'], Author.objects.get(pk=a.pk))
         self.assertTemplateUsed(res, 'generic_views/author_form.html')
@@ -237,6 +241,7 @@ class UpdateViewTests(TestCase):
         self.assertRedirects(res, 'http://testserver/list/authors/')
         self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (xkcd)>'])
 
+
 class DeleteViewTests(TestCase):
     urls = 'regressiontests.generic_views.urls'
 

+ 2 - 0
tests/regressiontests/generic_views/list.py

@@ -2,6 +2,7 @@ from __future__ import absolute_import
 
 from django.core.exceptions import ImproperlyConfigured
 from django.test import TestCase
+from django.views.generic.base import View
 
 from .models import Author, Artist
 
@@ -21,6 +22,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.assertTrue(isinstance(res.context['view'], View))
         self.assertIs(res.context['author_list'], res.context['object_list'])
         self.assertIsNone(res.context['paginator'])
         self.assertIsNone(res.context['page_obj'])