Merge pull request #1138 from ambv/issue20126

Fixed #20126 -- XViewMiddleware moved to django.contrib.admindocs.middleware
This commit is contained in:
Marc Tamlyn 2013-05-19 04:25:42 -07:00
commit 3d5a546254
12 changed files with 124 additions and 41 deletions

View File

@ -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

View File

@ -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

View File

@ -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`.

View File

@ -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
---------------

View File

@ -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

View File

@ -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
==========================

View File

View File

@ -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>

View File

45
tests/admin_docs/tests.py Normal file
View File

@ -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
tests/admin_docs/urls.py Normal file
View File

@ -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
tests/admin_docs/views.py Normal file
View File

@ -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()