diff options
| author | Claude Paroz <claude@2xlibre.net> | 2013-11-21 08:48:29 +0100 |
|---|---|---|
| committer | Claude Paroz <claude@2xlibre.net> | 2013-11-21 22:50:59 +0100 |
| commit | d6cc37d601166200e72385401f4384f818a18cfd (patch) | |
| tree | e78af8ec9c7640d92fdc2d17229d1b8bddda2f64 | |
| parent | 1718b5256cd65b8701e315e307c2eb2b5dd4c8d9 (diff) | |
Updated admindocs to use class-based views
Thanks Bouke Haarsma for the review.
| -rw-r--r-- | django/contrib/admindocs/templates/admin_doc/index.html | 2 | ||||
| -rw-r--r-- | django/contrib/admindocs/templates/admin_doc/missing_docutils.html | 2 | ||||
| -rw-r--r-- | django/contrib/admindocs/urls.py | 18 | ||||
| -rw-r--r-- | django/contrib/admindocs/views.py | 516 | ||||
| -rw-r--r-- | tests/admin_docs/tests.py | 86 | ||||
| -rw-r--r-- | tests/admin_docs/urls.py | 2 |
6 files changed, 350 insertions, 276 deletions
diff --git a/django/contrib/admindocs/templates/admin_doc/index.html b/django/contrib/admindocs/templates/admin_doc/index.html index 2af43d78c8..aa86a4b549 100644 --- a/django/contrib/admindocs/templates/admin_doc/index.html +++ b/django/contrib/admindocs/templates/admin_doc/index.html @@ -4,7 +4,7 @@ {% block breadcrumbs %} <div class="breadcrumbs"> <a href="{% url 'admin:index' %}">{% trans 'Home' %}</a> -› {% trans 'Documentation' %}</a> +› {% trans 'Documentation' %} </div> {% endblock %} {% block title %}{% trans 'Documentation' %}{% endblock %} diff --git a/django/contrib/admindocs/templates/admin_doc/missing_docutils.html b/django/contrib/admindocs/templates/admin_doc/missing_docutils.html index bd790f779a..123668f732 100644 --- a/django/contrib/admindocs/templates/admin_doc/missing_docutils.html +++ b/django/contrib/admindocs/templates/admin_doc/missing_docutils.html @@ -4,7 +4,7 @@ {% block breadcrumbs %} <div class="breadcrumbs"> <a href="{% url 'admin:index' %}">{% trans 'Home' %}</a> -› {% trans 'Documentation' %}</a> +› {% trans 'Documentation' %} </div> {% endblock %} {% block title %}{% trans 'Please install docutils' %}{% endblock %} diff --git a/django/contrib/admindocs/urls.py b/django/contrib/admindocs/urls.py index 4f50049f87..8aa4dcf946 100644 --- a/django/contrib/admindocs/urls.py +++ b/django/contrib/admindocs/urls.py @@ -3,39 +3,39 @@ from django.contrib.admindocs import views urlpatterns = patterns('', url('^$', - views.doc_index, + views.BaseAdminDocsView.as_view(template_name='admin_doc/index.html'), name='django-admindocs-docroot' ), url('^bookmarklets/$', - views.bookmarklets, + views.BookmarkletsView.as_view(), name='django-admindocs-bookmarklets' ), url('^tags/$', - views.template_tag_index, + views.TemplateTagIndexView.as_view(), name='django-admindocs-tags' ), url('^filters/$', - views.template_filter_index, + views.TemplateFilterIndexView.as_view(), name='django-admindocs-filters' ), url('^views/$', - views.view_index, + views.ViewIndexView.as_view(), name='django-admindocs-views-index' ), url('^views/(?P<view>[^/]+)/$', - views.view_detail, + views.ViewDetailView.as_view(), name='django-admindocs-views-detail' ), url('^models/$', - views.model_index, + views.ModelIndexView.as_view(), name='django-admindocs-models-index' ), url('^models/(?P<app_label>[^\.]+)\.(?P<model_name>[^/]+)/$', - views.model_detail, + views.ModelDetailView.as_view(), name='django-admindocs-models-detail' ), url('^templates/(?P<template>.*)/$', - views.template_detail, + views.TemplateDetailView.as_view(), name='django-admindocs-templates' ), ) diff --git a/django/contrib/admindocs/views.py b/django/contrib/admindocs/views.py index d8f00d5df0..b4caff82c7 100644 --- a/django/contrib/admindocs/views.py +++ b/django/contrib/admindocs/views.py @@ -4,19 +4,19 @@ import os import re from django import template -from django.template import RequestContext from django.conf import settings from django.contrib.admin.views.decorators import staff_member_required from django.db import models -from django.shortcuts import render_to_response from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist from django.http import Http404 from django.core import urlresolvers from django.contrib.admindocs import utils from django.contrib.sites.models import Site +from django.utils.decorators import method_decorator from django.utils._os import upath from django.utils import six from django.utils.translation import ugettext as _ +from django.views.generic import TemplateView # Exclude methods starting with these strings from documentation MODEL_METHODS_EXCLUDE = ('_', 'add_', 'delete', 'save', 'set_') @@ -27,301 +27,299 @@ class GenericSite(object): name = 'my site' -@staff_member_required -def doc_index(request): - if not utils.docutils_is_available: - return missing_docutils_page(request) - return render_to_response('admin_doc/index.html', { - 'root_path': urlresolvers.reverse('admin:index'), - }, context_instance=RequestContext(request)) +class BaseAdminDocsView(TemplateView): + """ + Base view for admindocs views. + """ + @method_decorator(staff_member_required) + def dispatch(self, *args, **kwargs): + if not utils.docutils_is_available: + # Display an error message for people without docutils + self.template_name = 'admin_doc/missing_docutils.html' + return self.render_to_response({}) + return super(BaseAdminDocsView, self).dispatch(*args, **kwargs) + def get_context_data(self, **kwargs): + kwargs.update({'root_path': urlresolvers.reverse('admin:index')}) + return super(BaseAdminDocsView, self).get_context_data(**kwargs) -@staff_member_required -def bookmarklets(request): - admin_root = urlresolvers.reverse('admin:index') - return render_to_response('admin_doc/bookmarklets.html', { - 'root_path': admin_root, - 'admin_url': "%s://%s%s" % (request.scheme, request.get_host(), admin_root), - }, context_instance=RequestContext(request)) +class BookmarkletsView(BaseAdminDocsView): + template_name = 'admin_doc/bookmarklets.html' -@staff_member_required -def template_tag_index(request): - if not utils.docutils_is_available: - return missing_docutils_page(request) + def get_context_data(self, **kwargs): + context = super(BookmarkletsView, self).get_context_data(**kwargs) + context.update({ + 'admin_url': "%s://%s%s" % ( + self.request.scheme, self.request.get_host(), context['root_path']) + }) + return context - load_all_installed_template_libraries() - tags = [] - app_libs = list(six.iteritems(template.libraries)) - builtin_libs = [(None, lib) for lib in template.builtins] - for module_name, library in builtin_libs + app_libs: - for tag_name, tag_func in library.tags.items(): - title, body, metadata = utils.parse_docstring(tag_func.__doc__) - if title: - title = utils.parse_rst(title, 'tag', _('tag:') + tag_name) - if body: - body = utils.parse_rst(body, 'tag', _('tag:') + tag_name) - for key in metadata: - metadata[key] = utils.parse_rst(metadata[key], 'tag', _('tag:') + tag_name) - if library in template.builtins: - tag_library = '' - else: - tag_library = module_name.split('.')[-1] - tags.append({ - 'name': tag_name, - 'title': title, - 'body': body, - 'meta': metadata, - 'library': tag_library, - }) - return render_to_response('admin_doc/template_tag_index.html', { - 'root_path': urlresolvers.reverse('admin:index'), - 'tags': tags - }, context_instance=RequestContext(request)) +class TemplateTagIndexView(BaseAdminDocsView): + template_name = 'admin_doc/template_tag_index.html' + def get_context_data(self, **kwargs): + load_all_installed_template_libraries() -@staff_member_required -def template_filter_index(request): - if not utils.docutils_is_available: - return missing_docutils_page(request) + tags = [] + app_libs = list(six.iteritems(template.libraries)) + builtin_libs = [(None, lib) for lib in template.builtins] + for module_name, library in builtin_libs + app_libs: + for tag_name, tag_func in library.tags.items(): + title, body, metadata = utils.parse_docstring(tag_func.__doc__) + if title: + title = utils.parse_rst(title, 'tag', _('tag:') + tag_name) + if body: + body = utils.parse_rst(body, 'tag', _('tag:') + tag_name) + for key in metadata: + metadata[key] = utils.parse_rst(metadata[key], 'tag', _('tag:') + tag_name) + if library in template.builtins: + tag_library = '' + else: + tag_library = module_name.split('.')[-1] + tags.append({ + 'name': tag_name, + 'title': title, + 'body': body, + 'meta': metadata, + 'library': tag_library, + }) + kwargs.update({'tags': tags}) + return super(TemplateTagIndexView, self).get_context_data(**kwargs) - load_all_installed_template_libraries() - filters = [] - app_libs = list(six.iteritems(template.libraries)) - builtin_libs = [(None, lib) for lib in template.builtins] - for module_name, library in builtin_libs + app_libs: - for filter_name, filter_func in library.filters.items(): - title, body, metadata = utils.parse_docstring(filter_func.__doc__) - if title: - title = utils.parse_rst(title, 'filter', _('filter:') + filter_name) - if body: - body = utils.parse_rst(body, 'filter', _('filter:') + filter_name) - for key in metadata: - metadata[key] = utils.parse_rst(metadata[key], 'filter', _('filter:') + filter_name) - if library in template.builtins: - tag_library = '' - else: - tag_library = module_name.split('.')[-1] - filters.append({ - 'name': filter_name, - 'title': title, - 'body': body, - 'meta': metadata, - 'library': tag_library, - }) - return render_to_response('admin_doc/template_filter_index.html', { - 'root_path': urlresolvers.reverse('admin:index'), - 'filters': filters - }, context_instance=RequestContext(request)) +class TemplateFilterIndexView(BaseAdminDocsView): + template_name = 'admin_doc/template_filter_index.html' + def get_context_data(self, **kwargs): + load_all_installed_template_libraries() -@staff_member_required -def view_index(request): - if not utils.docutils_is_available: - return missing_docutils_page(request) + filters = [] + app_libs = list(six.iteritems(template.libraries)) + builtin_libs = [(None, lib) for lib in template.builtins] + for module_name, library in builtin_libs + app_libs: + for filter_name, filter_func in library.filters.items(): + title, body, metadata = utils.parse_docstring(filter_func.__doc__) + if title: + title = utils.parse_rst(title, 'filter', _('filter:') + filter_name) + if body: + body = utils.parse_rst(body, 'filter', _('filter:') + filter_name) + for key in metadata: + metadata[key] = utils.parse_rst(metadata[key], 'filter', _('filter:') + filter_name) + if library in template.builtins: + tag_library = '' + else: + tag_library = module_name.split('.')[-1] + filters.append({ + 'name': filter_name, + 'title': title, + 'body': body, + 'meta': metadata, + 'library': tag_library, + }) + kwargs.update({'filters': filters}) + return super(TemplateFilterIndexView, self).get_context_data(**kwargs) - if settings.ADMIN_FOR: - settings_modules = [import_module(m) for m in settings.ADMIN_FOR] - else: - settings_modules = [settings] - views = [] - for settings_mod in settings_modules: - urlconf = import_module(settings_mod.ROOT_URLCONF) - view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns) - if Site._meta.installed: - site_obj = Site.objects.get(pk=settings_mod.SITE_ID) +class ViewIndexView(BaseAdminDocsView): + template_name = 'admin_doc/view_index.html' + + def get_context_data(self, **kwargs): + if settings.ADMIN_FOR: + settings_modules = [import_module(m) for m in settings.ADMIN_FOR] else: - site_obj = GenericSite() - for (func, regex) in view_functions: - views.append({ - 'full_name': '%s.%s' % (func.__module__, getattr(func, '__name__', func.__class__.__name__)), - 'site_id': settings_mod.SITE_ID, - 'site': site_obj, - 'url': simplify_regex(regex), - }) - return render_to_response('admin_doc/view_index.html', { - 'root_path': urlresolvers.reverse('admin:index'), - 'views': views - }, context_instance=RequestContext(request)) + settings_modules = [settings] + views = [] + for settings_mod in settings_modules: + urlconf = import_module(settings_mod.ROOT_URLCONF) + view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns) + if Site._meta.installed: + site_obj = Site.objects.get(pk=settings_mod.SITE_ID) + else: + site_obj = GenericSite() + for (func, regex) in view_functions: + views.append({ + 'full_name': '%s.%s' % (func.__module__, getattr(func, '__name__', func.__class__.__name__)), + 'site_id': settings_mod.SITE_ID, + 'site': site_obj, + 'url': simplify_regex(regex), + }) + kwargs.update({'views': views}) + return super(ViewIndexView, self).get_context_data(**kwargs) -@staff_member_required -def view_detail(request, view): - if not utils.docutils_is_available: - return missing_docutils_page(request) - mod, func = urlresolvers.get_mod_func(view) - try: - view_func = getattr(import_module(mod), func) - except (ImportError, AttributeError): - raise Http404 - title, body, metadata = utils.parse_docstring(view_func.__doc__) - if title: - title = utils.parse_rst(title, 'view', _('view:') + view) - if body: - body = utils.parse_rst(body, 'view', _('view:') + view) - for key in metadata: - metadata[key] = utils.parse_rst(metadata[key], 'model', _('view:') + view) - return render_to_response('admin_doc/view_detail.html', { - 'root_path': urlresolvers.reverse('admin:index'), - 'name': view, - 'summary': title, - 'body': body, - 'meta': metadata, - }, context_instance=RequestContext(request)) +class ViewDetailView(BaseAdminDocsView): + template_name = 'admin_doc/view_detail.html' + def get_context_data(self, **kwargs): + view = self.kwargs['view'] + mod, func = urlresolvers.get_mod_func(view) + try: + view_func = getattr(import_module(mod), func) + except (ImportError, AttributeError): + raise Http404 + title, body, metadata = utils.parse_docstring(view_func.__doc__) + if title: + title = utils.parse_rst(title, 'view', _('view:') + view) + if body: + body = utils.parse_rst(body, 'view', _('view:') + view) + for key in metadata: + metadata[key] = utils.parse_rst(metadata[key], 'model', _('view:') + view) + kwargs.update({ + 'name': view, + 'summary': title, + 'body': body, + 'meta': metadata, + }) + return super(ViewDetailView, self).get_context_data(**kwargs) -@staff_member_required -def model_index(request): - if not utils.docutils_is_available: - return missing_docutils_page(request) - m_list = [m._meta for m in models.get_models()] - return render_to_response('admin_doc/model_index.html', { - 'root_path': urlresolvers.reverse('admin:index'), - 'models': m_list - }, context_instance=RequestContext(request)) +class ModelIndexView(BaseAdminDocsView): + template_name = 'admin_doc/model_index.html' -@staff_member_required -def model_detail(request, app_label, model_name): - if not utils.docutils_is_available: - return missing_docutils_page(request) + def get_context_data(self, **kwargs): + m_list = [m._meta for m in models.get_models()] + kwargs.update({'models': m_list}) + return super(ModelIndexView, self).get_context_data(**kwargs) - # Get the model class. - try: - app_mod = models.get_app(app_label) - except ImproperlyConfigured: - raise Http404(_("App %r not found") % app_label) - model = None - for m in models.get_models(app_mod): - if m._meta.model_name == model_name: - model = m - break - if model is None: - raise Http404(_("Model %(model_name)r not found in app %(app_label)r") % {'model_name': model_name, 'app_label': app_label}) - opts = model._meta +class ModelDetailView(BaseAdminDocsView): + template_name = 'admin_doc/model_detail.html' - # Gather fields/field descriptions. - fields = [] - for field in opts.fields: - # ForeignKey is a special case since the field will actually be a - # descriptor that returns the other object - if isinstance(field, models.ForeignKey): - data_type = field.rel.to.__name__ - app_label = field.rel.to._meta.app_label - verbose = utils.parse_rst( - (_("the related `%(app_label)s.%(data_type)s` object") % { - 'app_label': app_label, 'data_type': data_type, - }), - 'model', - _('model:') + data_type, - ) - else: - data_type = get_readable_field_data_type(field) - verbose = field.verbose_name - fields.append({ - 'name': field.name, - 'data_type': data_type, - 'verbose': verbose, - 'help_text': field.help_text, - }) + def get_context_data(self, **kwargs): + # Get the model class. + try: + app_mod = models.get_app(self.kwargs['app_label']) + except ImproperlyConfigured: + raise Http404(_("App %r not found") % self.kwargs['app_label']) + model = None + for m in models.get_models(app_mod): + if m._meta.model_name == self.kwargs['model_name']: + model = m + break + if model is None: + raise Http404(_("Model %(model_name)r not found in app %(app_label)r") % { + 'model_name': self.kwargs['model_name'], 'app_label': self.kwargs['app_label']}) - # Gather many-to-many fields. - for field in opts.many_to_many: - data_type = field.rel.to.__name__ - app_label = field.rel.to._meta.app_label - verbose = _("related `%(app_label)s.%(object_name)s` objects") % {'app_label': app_label, 'object_name': data_type} - fields.append({ - 'name': "%s.all" % field.name, - "data_type": 'List', - 'verbose': utils.parse_rst(_("all %s") % verbose, 'model', _('model:') + opts.model_name), - }) - fields.append({ - 'name': "%s.count" % field.name, - 'data_type': 'Integer', - 'verbose': utils.parse_rst(_("number of %s") % verbose, 'model', _('model:') + opts.model_name), - }) + opts = model._meta - # Gather model methods. - for func_name, func in model.__dict__.items(): - if (inspect.isfunction(func) and len(inspect.getargspec(func)[0]) == 1): - try: - for exclude in MODEL_METHODS_EXCLUDE: - if func_name.startswith(exclude): - raise StopIteration - except StopIteration: - continue - verbose = func.__doc__ - if verbose: - verbose = utils.parse_rst(utils.trim_docstring(verbose), 'model', _('model:') + opts.model_name) + # Gather fields/field descriptions. + fields = [] + for field in opts.fields: + # ForeignKey is a special case since the field will actually be a + # descriptor that returns the other object + if isinstance(field, models.ForeignKey): + data_type = field.rel.to.__name__ + app_label = field.rel.to._meta.app_label + verbose = utils.parse_rst( + (_("the related `%(app_label)s.%(data_type)s` object") % { + 'app_label': app_label, 'data_type': data_type, + }), + 'model', + _('model:') + data_type, + ) + else: + data_type = get_readable_field_data_type(field) + verbose = field.verbose_name fields.append({ - 'name': func_name, - 'data_type': get_return_data_type(func_name), + 'name': field.name, + 'data_type': data_type, 'verbose': verbose, + 'help_text': field.help_text, }) - # Gather related objects - for rel in opts.get_all_related_objects() + opts.get_all_related_many_to_many_objects(): - verbose = _("related `%(app_label)s.%(object_name)s` objects") % {'app_label': rel.opts.app_label, 'object_name': rel.opts.object_name} - accessor = rel.get_accessor_name() - fields.append({ - 'name': "%s.all" % accessor, - 'data_type': 'List', - 'verbose': utils.parse_rst(_("all %s") % verbose, 'model', _('model:') + opts.model_name), - }) - fields.append({ - 'name': "%s.count" % accessor, - 'data_type': 'Integer', - 'verbose': utils.parse_rst(_("number of %s") % verbose, 'model', _('model:') + opts.model_name), - }) - return render_to_response('admin_doc/model_detail.html', { - 'root_path': urlresolvers.reverse('admin:index'), - 'name': '%s.%s' % (opts.app_label, opts.object_name), - # Translators: %s is an object type name - 'summary': _("Attributes on %s objects") % opts.object_name, - 'description': model.__doc__, - 'fields': fields, - }, context_instance=RequestContext(request)) + # Gather many-to-many fields. + for field in opts.many_to_many: + data_type = field.rel.to.__name__ + app_label = field.rel.to._meta.app_label + verbose = _("related `%(app_label)s.%(object_name)s` objects") % {'app_label': app_label, 'object_name': data_type} + fields.append({ + 'name': "%s.all" % field.name, + "data_type": 'List', + 'verbose': utils.parse_rst(_("all %s") % verbose, 'model', _('model:') + opts.model_name), + }) + fields.append({ + 'name': "%s.count" % field.name, + 'data_type': 'Integer', + 'verbose': utils.parse_rst(_("number of %s") % verbose, 'model', _('model:') + opts.model_name), + }) + # Gather model methods. + for func_name, func in model.__dict__.items(): + if (inspect.isfunction(func) and len(inspect.getargspec(func)[0]) == 1): + try: + for exclude in MODEL_METHODS_EXCLUDE: + if func_name.startswith(exclude): + raise StopIteration + except StopIteration: + continue + verbose = func.__doc__ + if verbose: + verbose = utils.parse_rst(utils.trim_docstring(verbose), 'model', _('model:') + opts.model_name) + fields.append({ + 'name': func_name, + 'data_type': get_return_data_type(func_name), + 'verbose': verbose, + }) -@staff_member_required -def template_detail(request, template): - templates = [] - for site_settings_module in settings.ADMIN_FOR: - settings_mod = import_module(site_settings_module) - if Site._meta.installed: - site_obj = Site.objects.get(pk=settings_mod.SITE_ID) - else: - site_obj = GenericSite() - for dir in settings_mod.TEMPLATE_DIRS: - template_file = os.path.join(dir, template) - templates.append({ - 'file': template_file, - 'exists': os.path.exists(template_file), - 'contents': lambda: open(template_file).read() if os.path.exists(template_file) else '', - 'site_id': settings_mod.SITE_ID, - 'site': site_obj, - 'order': list(settings_mod.TEMPLATE_DIRS).index(dir), + # Gather related objects + for rel in opts.get_all_related_objects() + opts.get_all_related_many_to_many_objects(): + verbose = _("related `%(app_label)s.%(object_name)s` objects") % {'app_label': rel.opts.app_label, 'object_name': rel.opts.object_name} + accessor = rel.get_accessor_name() + fields.append({ + 'name': "%s.all" % accessor, + 'data_type': 'List', + 'verbose': utils.parse_rst(_("all %s") % verbose, 'model', _('model:') + opts.model_name), + }) + fields.append({ + 'name': "%s.count" % accessor, + 'data_type': 'Integer', + 'verbose': utils.parse_rst(_("number of %s") % verbose, 'model', _('model:') + opts.model_name), }) - return render_to_response('admin_doc/template_detail.html', { - 'root_path': urlresolvers.reverse('admin:index'), - 'name': template, - 'templates': templates, - }, context_instance=RequestContext(request)) + kwargs.update({ + 'name': '%s.%s' % (opts.app_label, opts.object_name), + # Translators: %s is an object type name + 'summary': _("Attributes on %s objects") % opts.object_name, + 'description': model.__doc__, + 'fields': fields, + }) + return super(ModelDetailView, self).get_context_data(**kwargs) -#################### -# Helper functions # -#################### +class TemplateDetailView(BaseAdminDocsView): + template_name = 'admin_doc/template_detail.html' + + def get_context_data(self, **kwargs): + template = self.kwargs['template'] + templates = [] + for site_settings_module in settings.ADMIN_FOR: + settings_mod = import_module(site_settings_module) + if Site._meta.installed: + site_obj = Site.objects.get(pk=settings_mod.SITE_ID) + else: + site_obj = GenericSite() + for dir in settings_mod.TEMPLATE_DIRS: + template_file = os.path.join(dir, template) + templates.append({ + 'file': template_file, + 'exists': os.path.exists(template_file), + 'contents': lambda: open(template_file).read() if os.path.exists(template_file) else '', + 'site_id': settings_mod.SITE_ID, + 'site': site_obj, + 'order': list(settings_mod.TEMPLATE_DIRS).index(dir), + }) + kwargs.update({ + 'name': template, + 'templates': templates, + }) + return super(TemplateDetailView, self).get_context_data(**kwargs) -def missing_docutils_page(request): - """Display an error message for people without docutils""" - return render_to_response('admin_doc/missing_docutils.html') +#################### +# Helper functions # +#################### def load_all_installed_template_libraries(): # Load/register all template tag libraries from installed apps. diff --git a/tests/admin_docs/tests.py b/tests/admin_docs/tests.py index 3ae3a42843..d43205987e 100644 --- a/tests/admin_docs/tests.py +++ b/tests/admin_docs/tests.py @@ -1,17 +1,90 @@ import unittest -try: - import docutils -except ImportError: - docutils = None - from django.contrib.admindocs import utils from django.contrib.auth.models import User +from django.core.urlresolvers import reverse from django.test import TestCase from django.test.utils import override_settings @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) +@unittest.skipUnless(utils.docutils_is_available, "no docutils installed.") +class AdminDocViewTests(TestCase): + fixtures = ['data.xml'] + urls = 'admin_docs.urls' + + def setUp(self): + self.client.login(username='super', password='secret') + + def test_index(self): + self.client.logout() + response = self.client.get(reverse('django-admindocs-docroot')) + # Should display the login screen + self.assertContains(response, + '<input type="hidden" name="next" value="/admindocs/" />', html=True) + self.client.login(username='super', password='secret') + response = self.client.get(reverse('django-admindocs-docroot')) + self.assertContains(response, '<h1>Documentation</h1>', html=True) + + def test_bookmarklets(self): + response = self.client.get(reverse('django-admindocs-bookmarklets')) + self.assertContains(response, 'http://testserver/admin/doc/views/') + + def test_templatetag_index(self): + response = self.client.get(reverse('django-admindocs-tags')) + self.assertContains(response, '<h3 id="built_in-extends">extends</h3>', html=True) + + def test_templatefilter_index(self): + response = self.client.get(reverse('django-admindocs-filters')) + self.assertContains(response, '<h3 id="built_in-first">first</h3>', html=True) + + def test_view_index(self): + response = self.client.get(reverse('django-admindocs-views-index')) + self.assertContains(response, + '<h3><a href="/admindocs/views/django.contrib.admindocs.views.BaseAdminDocsView/">/admindocs/</a></h3>', + html=True) + + def test_view_detail(self): + response = self.client.get( + reverse('django-admindocs-views-detail', + args=['django.contrib.admindocs.views.BaseAdminDocsView'])) + # View docstring + self.assertContains(response, 'Base view for admindocs views.') + + def test_model_index(self): + response = self.client.get(reverse('django-admindocs-models-index')) + self.assertContains(response, '<h2 id="app-auth">Auth</h2>', html=True) + + def test_model_detail(self): + response = self.client.get(reverse('django-admindocs-models-detail', + args=['auth', 'user'])) + # Check for attribute, many-to-many field + self.assertContains(response, + '<tr><td>email</td><td>Email address</td><td>email address</td></tr>', html=True) + self.assertContains(response, + '<tr><td>user_permissions.all</td><td>List</td><td>' + '<p>all related <a class="reference external" href="/admindocs/models/auth.permission/">' + 'auth.Permission</a> objects</p></td></tr>', html=True) + + def test_template_detail(self): + response = self.client.get(reverse('django-admindocs-templates', + args=['admin_doc/template_detail.html'])) + self.assertContains(response, + '<h1>Template: "admin_doc/template_detail.html"</h1>', html=True) + + def test_missing_docutils(self): + utils.docutils_is_available = False + try: + response = self.client.get(reverse('django-admindocs-docroot')) + self.assertContains(response, + '<h3>The admin documentation system requires Python\'s ' + '<a href="http://docutils.sf.net/">docutils</a> library.</h3>', + html=True) + finally: + utils.docutils_is_available = True + + +@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class XViewMiddlewareTest(TestCase): fixtures = ['data.xml'] urls = 'admin_docs.urls' @@ -53,7 +126,7 @@ class XViewMiddlewareTest(TestCase): self.assertFalse('X-View' in response) -@unittest.skipUnless(docutils, "no docutils installed.") +@unittest.skipUnless(utils.docutils_is_available, "no docutils installed.") class DefaultRoleTest(TestCase): urls = 'admin_docs.urls' @@ -81,6 +154,7 @@ class DefaultRoleTest(TestCase): when ``publish_parts`` is used directly, by setting it to ``cmsreference``. See #6681. """ + import docutils self.assertNotEqual(docutils.parsers.rst.roles.DEFAULT_INTERPRETED_ROLE, 'cmsreference') source = 'reST, `interpreted text`, default role.' diff --git a/tests/admin_docs/urls.py b/tests/admin_docs/urls.py index 08eaf03632..2dcd0315be 100644 --- a/tests/admin_docs/urls.py +++ b/tests/admin_docs/urls.py @@ -1,8 +1,10 @@ from django.conf.urls import include, patterns +from django.contrib import admin from . import views urlpatterns = patterns('', + (r'^admin/', include(admin.site.urls)), (r'^admindocs/', include('django.contrib.admindocs.urls')), (r'^xview/func/$', views.xview_dec(views.xview)), (r'^xview/class/$', views.xview_dec(views.XViewClass.as_view())), |
