Browse Source

Fixed #20126 -- XViewMiddleware moved to django.contrib.admindocs.middleware

Łukasz Langa 12 years ago
parent
commit
660762681c

+ 23 - 0
django/contrib/admindocs/middleware.py

@@ -0,0 +1,23 @@
+from django.conf import settings
+from django import http
+
+class XViewMiddleware(object):
+    """
+    Adds an X-View header to internal HEAD requests -- used by the documentation system.
+    """
+    def process_view(self, request, view_func, view_args, view_kwargs):
+        """
+        If the request method is HEAD and either the IP is internal or the
+        user is a logged-in staff member, quickly return with an x-header
+        indicating the view function.  This is used by the documentation module
+        to lookup the view function for an arbitrary page.
+        """
+        assert hasattr(request, 'user'), (
+            "The XView middleware requires authentication middleware to be "
+            "installed. Edit your MIDDLEWARE_CLASSES setting to insert "
+            "'django.contrib.auth.middleware.AuthenticationMiddleware'.")
+        if request.method == 'HEAD' and (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or
+                                         (request.user.is_active and request.user.is_staff)):
+            response = http.HttpResponse()
+            response['X-View'] = "%s.%s" % (view_func.__module__, view_func.__name__)
+            return response

+ 5 - 22
django/middleware/doc.py

@@ -1,23 +1,6 @@
-from django.conf import settings
-from django import http
+"""XViewMiddleware has been moved to django.contrib.admindocs.middleware."""
 
-class XViewMiddleware(object):
-    """
-    Adds an X-View header to internal HEAD requests -- used by the documentation system.
-    """
-    def process_view(self, request, view_func, view_args, view_kwargs):
-        """
-        If the request method is HEAD and either the IP is internal or the
-        user is a logged-in staff member, quickly return with an x-header
-        indicating the view function.  This is used by the documentation module
-        to lookup the view function for an arbitrary page.
-        """
-        assert hasattr(request, 'user'), (
-            "The XView middleware requires authentication middleware to be "
-            "installed. Edit your MIDDLEWARE_CLASSES setting to insert "
-            "'django.contrib.auth.middleware.AuthenticationMiddleware'.")
-        if request.method == 'HEAD' and (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or
-                                         (request.user.is_active and request.user.is_staff)):
-            response = http.HttpResponse()
-            response['X-View'] = "%s.%s" % (view_func.__module__, view_func.__name__)
-            return response
+import warnings
+warnings.warn(__doc__, PendingDeprecationWarning, stacklevel=2)
+
+from django.contrib.admindocs.middleware import XViewMiddleware

+ 5 - 5
docs/ref/contrib/admin/admindocs.txt

@@ -31,7 +31,7 @@ the following:
 * **Optional:** Linking to templates requires the :setting:`ADMIN_FOR`
   setting to be configured.
 * **Optional:** Using the admindocs bookmarklets requires the
-  :mod:`XViewMiddleware<django.middleware.doc>` to be installed.
+  :mod:`XViewMiddleware<django.contrib.admindocs.middleware>` to be installed.
 
 Once those steps are complete, you can start browsing the documentation by
 going to your admin interface and clicking the "Documentation" link in the
@@ -156,7 +156,7 @@ Edit this object
 Using these bookmarklets requires that you are either logged into the
 :mod:`Django admin <django.contrib.admin>` as a
 :class:`~django.contrib.auth.models.User` with
-:attr:`~django.contrib.auth.models.User.is_staff` set to `True`, or
-that the :mod:`django.middleware.doc` middleware and
-:mod:`XViewMiddleware <django.middleware.doc>` are installed and you
-are accessing the site from an IP address listed in :setting:`INTERNAL_IPS`.
+:attr:`~django.contrib.auth.models.User.is_staff` set to `True`, or that the
+:mod:`XViewMiddleware <django.contrib.admindocs.middleware>` is installed and
+you are accessing the site from an IP address listed in
+:setting:`INTERNAL_IPS`.

+ 0 - 13
docs/ref/middleware.txt

@@ -71,19 +71,6 @@ Adds a few conveniences for perfectionists:
 * Sends broken link notification emails to :setting:`MANAGERS` (see
   :doc:`/howto/error-reporting`).
 
-View metadata middleware
-------------------------
-
-.. module:: django.middleware.doc
-   :synopsis: Middleware to help your app self-document.
-
-.. class:: XViewMiddleware
-
-Sends custom ``X-View`` HTTP headers to HEAD requests that come from IP
-addresses defined in the :setting:`INTERNAL_IPS` setting. This is used by
-Django's :doc:`automatic documentation system </ref/contrib/admin/admindocs>`.
-Depends on :class:`~django.contrib.auth.middleware.AuthenticationMiddleware`.
-
 GZip middleware
 ---------------
 

+ 1 - 1
docs/ref/settings.txt

@@ -1243,7 +1243,7 @@ Default: ``()`` (Empty tuple)
 A tuple of IP addresses, as strings, that:
 
 * See debug comments, when :setting:`DEBUG` is ``True``
-* Receive X headers if the ``XViewMiddleware`` is installed (see
+* Receive X headers in admindocs if the ``XViewMiddleware`` is installed (see
   :doc:`/topics/http/middleware`)
 
 .. setting:: LANGUAGE_CODE

+ 4 - 0
docs/releases/1.6.txt

@@ -502,6 +502,10 @@ Miscellaneous
   ineffective so it has been removed, along with its generic implementation,
   previously available in ``django.core.xheaders``.
 
+* The ``XViewMiddleware`` has been moved from ``django.middleware.doc`` to
+  ``django.contrib.admindocs.middleware`` because it is an implementation
+  detail of admindocs, proven not to be reusable in general.
+
 Features deprecated in 1.6
 ==========================
 

+ 0 - 0
tests/admin_docs/__init__.py


+ 17 - 0
tests/admin_docs/fixtures/data.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<django-objects version="1.0">
+    <object pk="100" model="auth.user">
+        <field type="CharField" name="username">super</field>
+        <field type="CharField" name="first_name">Super</field>
+        <field type="CharField" name="last_name">User</field>
+        <field type="CharField" name="email">super@example.com</field>
+        <field type="CharField" name="password">sha1$995a3$6011485ea3834267d719b4c801409b8b1ddd0158</field>
+        <field type="BooleanField" name="is_staff">True</field>
+        <field type="BooleanField" name="is_active">True</field>
+        <field type="BooleanField" name="is_superuser">True</field>
+        <field type="DateTimeField" name="last_login">2007-05-30 13:20:10</field>
+        <field type="DateTimeField" name="date_joined">2007-05-30 13:20:10</field>
+        <field to="auth.group" name="groups" rel="ManyToManyRel"></field>
+        <field to="auth.permission" name="user_permissions" rel="ManyToManyRel"></field>
+    </object>
+</django-objects>

+ 0 - 0
tests/admin_docs/models.py


+ 45 - 0
tests/admin_docs/tests.py

@@ -0,0 +1,45 @@
+from django.contrib.auth.models import User
+from django.test import TestCase
+from django.test.utils import override_settings
+
+
+@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
+class XViewMiddlewareTest(TestCase):
+    fixtures = ['data.xml']
+    urls = 'admin_docs.urls'
+
+    def test_xview_func(self):
+        user = User.objects.get(username='super')
+        response = self.client.head('/xview/func/')
+        self.assertFalse('X-View' in response)
+        self.client.login(username='super', password='secret')
+        response = self.client.head('/xview/func/')
+        self.assertTrue('X-View' in response)
+        self.assertEqual(response['X-View'], 'admin_docs.views.xview')
+        user.is_staff = False
+        user.save()
+        response = self.client.head('/xview/func/')
+        self.assertFalse('X-View' in response)
+        user.is_staff = True
+        user.is_active = False
+        user.save()
+        response = self.client.head('/xview/func/')
+        self.assertFalse('X-View' in response)
+
+    def test_xview_class(self):
+        user = User.objects.get(username='super')
+        response = self.client.head('/xview/class/')
+        self.assertFalse('X-View' in response)
+        self.client.login(username='super', password='secret')
+        response = self.client.head('/xview/class/')
+        self.assertTrue('X-View' in response)
+        self.assertEqual(response['X-View'], 'admin_docs.views.XViewClass')
+        user.is_staff = False
+        user.save()
+        response = self.client.head('/xview/class/')
+        self.assertFalse('X-View' in response)
+        user.is_staff = True
+        user.is_active = False
+        user.save()
+        response = self.client.head('/xview/class/')
+        self.assertFalse('X-View' in response)

+ 11 - 0
tests/admin_docs/urls.py

@@ -0,0 +1,11 @@
+# coding: utf-8
+from __future__ import absolute_import
+
+from django.conf.urls import patterns
+
+from . import views
+
+urlpatterns = patterns('',
+    (r'^xview/func/$', views.xview_dec(views.xview)),
+    (r'^xview/class/$', views.xview_dec(views.XViewClass.as_view())),
+)

+ 13 - 0
tests/admin_docs/views.py

@@ -0,0 +1,13 @@
+from django.http import HttpResponse
+from django.utils.decorators import decorator_from_middleware
+from django.views.generic import View
+from django.contrib.admindocs.middleware import XViewMiddleware
+
+xview_dec = decorator_from_middleware(XViewMiddleware)
+
+def xview(request):
+    return HttpResponse()
+
+class XViewClass(View):
+    def get(self, request):
+        return HttpResponse()