Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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

…ontext

Updated the most recent patch from @claudep to apply again and updated
the documentation location.
  • Loading branch information...
commit 58683e9c82d6e7c5fbb7acef79eef9408b776ab0 1 parent 547b181
Marc Tamlyn authored August 18, 2012 andrewgodwin committed August 18, 2012
2  django/views/generic/base.py
@@ -18,6 +18,8 @@ class ContextMixin(object):
18 18
     """
19 19
 
20 20
     def get_context_data(self, **kwargs):
  21
+        if 'view' not in kwargs:
  22
+            kwargs['view'] = self
21 23
         return kwargs
22 24
 
23 25
 
16  docs/ref/class-based-views/mixins-simple.txt
@@ -17,8 +17,20 @@ ContextMixin
17 17
 
18 18
     .. method:: get_context_data(**kwargs)
19 19
 
20  
-        Returns a dictionary representing the template context. The
21  
-        keyword arguments provided will make up the returned context.
  20
+        Returns a dictionary representing the template context. The keyword
  21
+        arguments provided will make up the returned context.
  22
+
  23
+        The template context of all class-based generic views include a
  24
+        ``view`` variable that points to the ``View`` instance.
  25
+
  26
+        .. admonition:: Use ``alters_data`` where appropriate
  27
+
  28
+            Note that having the view instance in the template context may
  29
+            expose potentially hazardous methods to template authors.  To
  30
+            prevent methods like this from being called in the template, set
  31
+            ``alters_data=True`` on those methods.  For more information, read
  32
+            the documentation on :ref:`rendering a template context
  33
+            <alters-data-description>`.
22 34
 
23 35
 TemplateResponseMixin
24 36
 ---------------------
2  docs/ref/templates/api.txt
@@ -198,6 +198,8 @@ straight lookups. Here are some things to keep in mind:
198 198
 * A variable can only be called if it has no required arguments. Otherwise,
199 199
   the system will return an empty string.
200 200
 
  201
+.. _alters-data-description:
  202
+
201 203
 * Obviously, there can be side effects when calling some variables, and
202 204
   it'd be either foolish or a security hole to allow the template system
203 205
   to access them.
6  docs/releases/1.5.txt
@@ -84,6 +84,12 @@ By passing ``False`` using this argument it is now possible to retreive the
84 84
 :class:`ContentType <django.contrib.contenttypes.models.ContentType>`
85 85
 associated with proxy models.
86 86
 
  87
+New ``view`` variable in class-based views context
  88
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  89
+In all :doc:`generic class-based views </topics/class-based-views/index>`
  90
+(or any class-based view inheriting from ``ContextMixin``), the context dictionary
  91
+contains a ``view`` variable that points to the ``View`` instance.
  92
+
87 93
 Minor features
88 94
 ~~~~~~~~~~~~~~
89 95
 
2  tests/regressiontests/generic_views/base.py
@@ -276,6 +276,7 @@ def test_template_params(self):
276 276
         response = self.client.get('/template/simple/bar/')
277 277
         self.assertEqual(response.status_code, 200)
278 278
         self.assertEqual(response.context['params'], {'foo': 'bar'})
  279
+        self.assertTrue(isinstance(response.context['view'], View))
279 280
 
280 281
     def test_extra_template_params(self):
281 282
         """
@@ -285,6 +286,7 @@ def test_extra_template_params(self):
285 286
         self.assertEqual(response.status_code, 200)
286 287
         self.assertEqual(response.context['params'], {'foo': 'bar'})
287 288
         self.assertEqual(response.context['key'], 'value')
  289
+        self.assertTrue(isinstance(response.context['view'], View))
288 290
 
289 291
     def test_cached_views(self):
290 292
         """
2  tests/regressiontests/generic_views/detail.py
@@ -2,6 +2,7 @@
2 2
 
3 3
 from django.core.exceptions import ImproperlyConfigured
4 4
 from django.test import TestCase
  5
+from django.views.generic.base import View
5 6
 
6 7
 from .models import Artist, Author, Page
7 8
 
@@ -14,6 +15,7 @@ def test_simple_object(self):
14 15
         res = self.client.get('/detail/obj/')
15 16
         self.assertEqual(res.status_code, 200)
16 17
         self.assertEqual(res.context['object'], {'foo': 'bar'})
  18
+        self.assertTrue(isinstance(res.context['view'], View))
17 19
         self.assertTemplateUsed(res, 'generic_views/detail.html')
18 20
 
19 21
     def test_detail_by_pk(self):
5  tests/regressiontests/generic_views/edit.py
@@ -5,6 +5,7 @@
5 5
 from django import forms
6 6
 from django.test import TestCase
7 7
 from django.utils.unittest import expectedFailure
  8
+from django.views.generic.base import View
8 9
 from django.views.generic.edit import FormMixin
9 10
 
10 11
 from . import views
@@ -31,6 +32,7 @@ def test_create(self):
31 32
         res = self.client.get('/edit/authors/create/')
32 33
         self.assertEqual(res.status_code, 200)
33 34
         self.assertTrue(isinstance(res.context['form'], forms.ModelForm))
  35
+        self.assertTrue(isinstance(res.context['view'], View))
34 36
         self.assertFalse('object' in res.context)
35 37
         self.assertFalse('author' in res.context)
36 38
         self.assertTemplateUsed(res, 'generic_views/author_form.html')
@@ -101,6 +103,7 @@ def test_create_restricted(self):
101 103
         self.assertEqual(res.status_code, 302)
102 104
         self.assertRedirects(res, 'http://testserver/accounts/login/?next=/edit/authors/create/restricted/')
103 105
 
  106
+
104 107
 class UpdateViewTests(TestCase):
105 108
     urls = 'regressiontests.generic_views.urls'
106 109
 
@@ -226,6 +229,7 @@ def test_update_get_object(self):
226 229
         res = self.client.get('/edit/author/update/')
227 230
         self.assertEqual(res.status_code, 200)
228 231
         self.assertTrue(isinstance(res.context['form'], forms.ModelForm))
  232
+        self.assertTrue(isinstance(res.context['view'], View))
229 233
         self.assertEqual(res.context['object'], Author.objects.get(pk=a.pk))
230 234
         self.assertEqual(res.context['author'], Author.objects.get(pk=a.pk))
231 235
         self.assertTemplateUsed(res, 'generic_views/author_form.html')
@@ -237,6 +241,7 @@ def test_update_get_object(self):
237 241
         self.assertRedirects(res, 'http://testserver/list/authors/')
238 242
         self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (xkcd)>'])
239 243
 
  244
+
240 245
 class DeleteViewTests(TestCase):
241 246
     urls = 'regressiontests.generic_views.urls'
242 247
 
2  tests/regressiontests/generic_views/list.py
@@ -2,6 +2,7 @@
2 2
 
3 3
 from django.core.exceptions import ImproperlyConfigured
4 4
 from django.test import TestCase
  5
+from django.views.generic.base import View
5 6
 
6 7
 from .models import Author, Artist
7 8
 
@@ -21,6 +22,7 @@ def test_queryset(self):
21 22
         self.assertEqual(res.status_code, 200)
22 23
         self.assertTemplateUsed(res, 'generic_views/author_list.html')
23 24
         self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
  25
+        self.assertTrue(isinstance(res.context['view'], View))
24 26
         self.assertIs(res.context['author_list'], res.context['object_list'])
25 27
         self.assertIsNone(res.context['paginator'])
26 28
         self.assertIsNone(res.context['page_obj'])

0 notes on commit 58683e9

Please sign in to comment.
Something went wrong with that request. Please try again.