Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Merge pull request #1138 from ambv/issue20126

Fixed #20126 -- XViewMiddleware moved to django.contrib.admindocs.middleware
  • Loading branch information...
commit 3d5a546254b357ad27d5465700945e2bc472c3bc 2 parents a7e2835 + 6607626
Marc Tamlyn authored May 19, 2013
23  django/contrib/admindocs/middleware.py
... ...
@@ -0,0 +1,23 @@
  1
+from django.conf import settings
  2
+from django import http
  3
+
  4
+class XViewMiddleware(object):
  5
+    """
  6
+    Adds an X-View header to internal HEAD requests -- used by the documentation system.
  7
+    """
  8
+    def process_view(self, request, view_func, view_args, view_kwargs):
  9
+        """
  10
+        If the request method is HEAD and either the IP is internal or the
  11
+        user is a logged-in staff member, quickly return with an x-header
  12
+        indicating the view function.  This is used by the documentation module
  13
+        to lookup the view function for an arbitrary page.
  14
+        """
  15
+        assert hasattr(request, 'user'), (
  16
+            "The XView middleware requires authentication middleware to be "
  17
+            "installed. Edit your MIDDLEWARE_CLASSES setting to insert "
  18
+            "'django.contrib.auth.middleware.AuthenticationMiddleware'.")
  19
+        if request.method == 'HEAD' and (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or
  20
+                                         (request.user.is_active and request.user.is_staff)):
  21
+            response = http.HttpResponse()
  22
+            response['X-View'] = "%s.%s" % (view_func.__module__, view_func.__name__)
  23
+            return response
27  django/middleware/doc.py
... ...
@@ -1,23 +1,6 @@
1  
-from django.conf import settings
2  
-from django import http
  1
+"""XViewMiddleware has been moved to django.contrib.admindocs.middleware."""
3 2
 
4  
-class XViewMiddleware(object):
5  
-    """
6  
-    Adds an X-View header to internal HEAD requests -- used by the documentation system.
7  
-    """
8  
-    def process_view(self, request, view_func, view_args, view_kwargs):
9  
-        """
10  
-        If the request method is HEAD and either the IP is internal or the
11  
-        user is a logged-in staff member, quickly return with an x-header
12  
-        indicating the view function.  This is used by the documentation module
13  
-        to lookup the view function for an arbitrary page.
14  
-        """
15  
-        assert hasattr(request, 'user'), (
16  
-            "The XView middleware requires authentication middleware to be "
17  
-            "installed. Edit your MIDDLEWARE_CLASSES setting to insert "
18  
-            "'django.contrib.auth.middleware.AuthenticationMiddleware'.")
19  
-        if request.method == 'HEAD' and (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or
20  
-                                         (request.user.is_active and request.user.is_staff)):
21  
-            response = http.HttpResponse()
22  
-            response['X-View'] = "%s.%s" % (view_func.__module__, view_func.__name__)
23  
-            return response
  3
+import warnings
  4
+warnings.warn(__doc__, PendingDeprecationWarning, stacklevel=2)
  5
+
  6
+from django.contrib.admindocs.middleware import XViewMiddleware
10  docs/ref/contrib/admin/admindocs.txt
@@ -31,7 +31,7 @@ the following:
31 31
 * **Optional:** Linking to templates requires the :setting:`ADMIN_FOR`
32 32
   setting to be configured.
33 33
 * **Optional:** Using the admindocs bookmarklets requires the
34  
-  :mod:`XViewMiddleware<django.middleware.doc>` to be installed.
  34
+  :mod:`XViewMiddleware<django.contrib.admindocs.middleware>` to be installed.
35 35
 
36 36
 Once those steps are complete, you can start browsing the documentation by
37 37
 going to your admin interface and clicking the "Documentation" link in the
@@ -156,7 +156,7 @@ Edit this object
156 156
 Using these bookmarklets requires that you are either logged into the
157 157
 :mod:`Django admin <django.contrib.admin>` as a
158 158
 :class:`~django.contrib.auth.models.User` with
159  
-:attr:`~django.contrib.auth.models.User.is_staff` set to `True`, or
160  
-that the :mod:`django.middleware.doc` middleware and
161  
-:mod:`XViewMiddleware <django.middleware.doc>` are installed and you
162  
-are accessing the site from an IP address listed in :setting:`INTERNAL_IPS`.
  159
+:attr:`~django.contrib.auth.models.User.is_staff` set to `True`, or that the
  160
+:mod:`XViewMiddleware <django.contrib.admindocs.middleware>` is installed and
  161
+you are accessing the site from an IP address listed in
  162
+:setting:`INTERNAL_IPS`.
13  docs/ref/middleware.txt
@@ -71,19 +71,6 @@ Adds a few conveniences for perfectionists:
71 71
 * Sends broken link notification emails to :setting:`MANAGERS` (see
72 72
   :doc:`/howto/error-reporting`).
73 73
 
74  
-View metadata middleware
75  
-------------------------
76  
-
77  
-.. module:: django.middleware.doc
78  
-   :synopsis: Middleware to help your app self-document.
79  
-
80  
-.. class:: XViewMiddleware
81  
-
82  
-Sends custom ``X-View`` HTTP headers to HEAD requests that come from IP
83  
-addresses defined in the :setting:`INTERNAL_IPS` setting. This is used by
84  
-Django's :doc:`automatic documentation system </ref/contrib/admin/admindocs>`.
85  
-Depends on :class:`~django.contrib.auth.middleware.AuthenticationMiddleware`.
86  
-
87 74
 GZip middleware
88 75
 ---------------
89 76
 
2  docs/ref/settings.txt
@@ -1243,7 +1243,7 @@ Default: ``()`` (Empty tuple)
1243 1243
 A tuple of IP addresses, as strings, that:
1244 1244
 
1245 1245
 * See debug comments, when :setting:`DEBUG` is ``True``
1246  
-* Receive X headers if the ``XViewMiddleware`` is installed (see
  1246
+* Receive X headers in admindocs if the ``XViewMiddleware`` is installed (see
1247 1247
   :doc:`/topics/http/middleware`)
1248 1248
 
1249 1249
 .. setting:: LANGUAGE_CODE
4  docs/releases/1.6.txt
@@ -502,6 +502,10 @@ Miscellaneous
502 502
   ineffective so it has been removed, along with its generic implementation,
503 503
   previously available in ``django.core.xheaders``.
504 504
 
  505
+* The ``XViewMiddleware`` has been moved from ``django.middleware.doc`` to
  506
+  ``django.contrib.admindocs.middleware`` because it is an implementation
  507
+  detail of admindocs, proven not to be reusable in general.
  508
+
505 509
 Features deprecated in 1.6
506 510
 ==========================
507 511
 
0  tests/admin_docs/__init__.py
No changes.
17  tests/admin_docs/fixtures/data.xml
... ...
@@ -0,0 +1,17 @@
  1
+<?xml version="1.0" encoding="utf-8"?>
  2
+<django-objects version="1.0">
  3
+    <object pk="100" model="auth.user">
  4
+        <field type="CharField" name="username">super</field>
  5
+        <field type="CharField" name="first_name">Super</field>
  6
+        <field type="CharField" name="last_name">User</field>
  7
+        <field type="CharField" name="email">super@example.com</field>
  8
+        <field type="CharField" name="password">sha1$995a3$6011485ea3834267d719b4c801409b8b1ddd0158</field>
  9
+        <field type="BooleanField" name="is_staff">True</field>
  10
+        <field type="BooleanField" name="is_active">True</field>
  11
+        <field type="BooleanField" name="is_superuser">True</field>
  12
+        <field type="DateTimeField" name="last_login">2007-05-30 13:20:10</field>
  13
+        <field type="DateTimeField" name="date_joined">2007-05-30 13:20:10</field>
  14
+        <field to="auth.group" name="groups" rel="ManyToManyRel"></field>
  15
+        <field to="auth.permission" name="user_permissions" rel="ManyToManyRel"></field>
  16
+    </object>
  17
+</django-objects>
0  tests/admin_docs/models.py
No changes.
45  tests/admin_docs/tests.py
... ...
@@ -0,0 +1,45 @@
  1
+from django.contrib.auth.models import User
  2
+from django.test import TestCase
  3
+from django.test.utils import override_settings
  4
+
  5
+
  6
+@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
  7
+class XViewMiddlewareTest(TestCase):
  8
+    fixtures = ['data.xml']
  9
+    urls = 'admin_docs.urls'
  10
+
  11
+    def test_xview_func(self):
  12
+        user = User.objects.get(username='super')
  13
+        response = self.client.head('/xview/func/')
  14
+        self.assertFalse('X-View' in response)
  15
+        self.client.login(username='super', password='secret')
  16
+        response = self.client.head('/xview/func/')
  17
+        self.assertTrue('X-View' in response)
  18
+        self.assertEqual(response['X-View'], 'admin_docs.views.xview')
  19
+        user.is_staff = False
  20
+        user.save()
  21
+        response = self.client.head('/xview/func/')
  22
+        self.assertFalse('X-View' in response)
  23
+        user.is_staff = True
  24
+        user.is_active = False
  25
+        user.save()
  26
+        response = self.client.head('/xview/func/')
  27
+        self.assertFalse('X-View' in response)
  28
+
  29
+    def test_xview_class(self):
  30
+        user = User.objects.get(username='super')
  31
+        response = self.client.head('/xview/class/')
  32
+        self.assertFalse('X-View' in response)
  33
+        self.client.login(username='super', password='secret')
  34
+        response = self.client.head('/xview/class/')
  35
+        self.assertTrue('X-View' in response)
  36
+        self.assertEqual(response['X-View'], 'admin_docs.views.XViewClass')
  37
+        user.is_staff = False
  38
+        user.save()
  39
+        response = self.client.head('/xview/class/')
  40
+        self.assertFalse('X-View' in response)
  41
+        user.is_staff = True
  42
+        user.is_active = False
  43
+        user.save()
  44
+        response = self.client.head('/xview/class/')
  45
+        self.assertFalse('X-View' in response)
11  tests/admin_docs/urls.py
... ...
@@ -0,0 +1,11 @@
  1
+# coding: utf-8
  2
+from __future__ import absolute_import
  3
+
  4
+from django.conf.urls import patterns
  5
+
  6
+from . import views
  7
+
  8
+urlpatterns = patterns('',
  9
+    (r'^xview/func/$', views.xview_dec(views.xview)),
  10
+    (r'^xview/class/$', views.xview_dec(views.XViewClass.as_view())),
  11
+)
13  tests/admin_docs/views.py
... ...
@@ -0,0 +1,13 @@
  1
+from django.http import HttpResponse
  2
+from django.utils.decorators import decorator_from_middleware
  3
+from django.views.generic import View
  4
+from django.contrib.admindocs.middleware import XViewMiddleware
  5
+
  6
+xview_dec = decorator_from_middleware(XViewMiddleware)
  7
+
  8
+def xview(request):
  9
+    return HttpResponse()
  10
+
  11
+class XViewClass(View):
  12
+    def get(self, request):
  13
+        return HttpResponse()

0 notes on commit 3d5a546

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