diff --git a/django/views/generic/base.py b/django/views/generic/base.py
index c32a58a..f1e786c 100644
a
|
b
|
class ContextMixin(object):
|
15 | 15 | """ |
16 | 16 | |
17 | 17 | def get_context_data(self, **kwargs): |
| 18 | if 'view' not in kwargs: |
| 19 | kwargs['view'] = self |
18 | 20 | return kwargs |
19 | 21 | |
20 | 22 | |
diff --git a/django/views/generic/edit.py b/django/views/generic/edit.py
index 1f488cb..ab27a89 100644
a
|
b
|
class FormMixin(ContextMixin):
|
35 | 35 | |
36 | 36 | def get_form_kwargs(self): |
37 | 37 | """ |
38 | | Returns the keyword arguments for instanciating the form. |
| 38 | Returns the keyword arguments for instantiating the form. |
39 | 39 | """ |
40 | 40 | kwargs = {'initial': self.get_initial()} |
41 | 41 | if self.request.method in ('POST', 'PUT'): |
diff --git a/docs/ref/class-based-views.txt b/docs/ref/class-based-views.txt
index 5223aee..005f38f 100644
a
|
b
|
View
|
884 | 884 | The default implementation returns ``HttpResponseNotAllowed`` with list |
885 | 885 | of allowed methods in plain text. |
886 | 886 | |
| 887 | **Context** |
| 888 | |
| 889 | .. versionadded:: 1.5 |
| 890 | |
| 891 | * ``view``: The template context of all class-based generic views include |
| 892 | a ``view`` variable that points to the ``View`` instance. |
| 893 | |
| 894 | .. admonition:: Use ``alters_data`` where appropriate |
| 895 | |
| 896 | Note that having the view instance in the template context may expose |
| 897 | potentially hazardous methods to template authors. To prevent methods |
| 898 | like this from being called in the template, set ``alters_data=True`` |
| 899 | on those methods. For more information, read the documentation on |
| 900 | :ref:`rendering a template context <alters-data-description>`. |
| 901 | |
| 902 | |
887 | 903 | TemplateView |
888 | 904 | ~~~~~~~~~~~~ |
889 | 905 | .. class:: TemplateView() |
diff --git a/docs/ref/templates/api.txt b/docs/ref/templates/api.txt
index 03fef1d..2bb20f9 100644
a
|
b
|
straight lookups. Here are some things to keep in mind:
|
195 | 195 | * A variable can only be called if it has no required arguments. Otherwise, |
196 | 196 | the system will return an empty string. |
197 | 197 | |
| 198 | .. _alters-data-description: |
| 199 | |
198 | 200 | * Obviously, there can be side effects when calling some variables, and |
199 | 201 | it'd be either foolish or a security hole to allow the template system |
200 | 202 | to access them. |
diff --git a/docs/releases/1.5.txt b/docs/releases/1.5.txt
index 84459f9..731ff02 100644
a
|
b
|
Django 1.5 does not run on Jython.
|
33 | 33 | What's new in Django 1.5 |
34 | 34 | ======================== |
35 | 35 | |
| 36 | New ``view`` variable in class-based views context |
| 37 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 38 | In all :doc:`generic class-based views </topics/class-based-views>` |
| 39 | (or any class-based view inheriting from ``ContextMixin``), the context dictionary |
| 40 | contains a ``view`` variable that points to the ``View`` instance. |
| 41 | |
36 | 42 | Backwards incompatible changes in 1.5 |
37 | 43 | ===================================== |
38 | 44 | |
diff --git a/tests/regressiontests/generic_views/base.py b/tests/regressiontests/generic_views/base.py
index e18ed2a..af1f48c 100644
a
|
b
|
class TemplateViewTest(TestCase):
|
224 | 224 | response = self.client.get('/template/simple/bar/') |
225 | 225 | self.assertEqual(response.status_code, 200) |
226 | 226 | self.assertEqual(response.context['params'], {'foo': 'bar'}) |
| 227 | self.assertTrue(isinstance(response.context['view'], View)) |
227 | 228 | |
228 | 229 | def test_extra_template_params(self): |
229 | 230 | """ |
… |
… |
class TemplateViewTest(TestCase):
|
233 | 234 | self.assertEqual(response.status_code, 200) |
234 | 235 | self.assertEqual(response.context['params'], {'foo': 'bar'}) |
235 | 236 | self.assertEqual(response.context['key'], 'value') |
| 237 | self.assertTrue(isinstance(response.context['view'], View)) |
236 | 238 | |
237 | 239 | def test_cached_views(self): |
238 | 240 | """ |
diff --git a/tests/regressiontests/generic_views/detail.py b/tests/regressiontests/generic_views/detail.py
index 0b5d873..24c73f3 100644
a
|
b
|
from __future__ import absolute_import
|
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 | |
… |
… |
class DetailViewTest(TestCase):
|
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): |
diff --git a/tests/regressiontests/generic_views/edit.py b/tests/regressiontests/generic_views/edit.py
index 651e14f..16f4da8 100644
a
|
b
|
from django.core.urlresolvers import reverse
|
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 |
… |
… |
class CreateViewTests(TestCase):
|
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') |
… |
… |
class CreateViewTests(TestCase):
|
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 | |
… |
… |
class UpdateViewTests(TestCase):
|
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') |
… |
… |
class UpdateViewTests(TestCase):
|
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 | |
diff --git a/tests/regressiontests/generic_views/list.py b/tests/regressiontests/generic_views/list.py
index 9ad00ed..47d6b18 100644
a
|
b
|
from __future__ import absolute_import
|
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 | |
… |
… |
class ListViewTests(TestCase):
|
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']) |