Made a bunch of fixes to auto-generated admin documentation:
* Views are no longer "doubled" * Links work better (view -> model links and friends were broken) * Performance has been improved so now the pages no longer need to be cached. git-svn-id: http://code.djangoproject.com/svn/django/trunk@391 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
ffc3edd79e
commit
ce0d0cd9e2
|
@ -67,6 +67,8 @@ code, pre { font-family:"Bitstream Vera Sans Mono", Monaco, "Courier New", Couri
|
||||||
pre.literal-block { margin:10px; background:#eee; padding:6px 8px; }
|
pre.literal-block { margin:10px; background:#eee; padding:6px 8px; }
|
||||||
code strong { color:#930; }
|
code strong { color:#930; }
|
||||||
hr { clear:both; color:#eee; background-color:#eee; height:1px; border:none; margin:0; padding:0; font-size:1px; line-height:1px; }
|
hr { clear:both; color:#eee; background-color:#eee; height:1px; border:none; margin:0; padding:0; font-size:1px; line-height:1px; }
|
||||||
|
div.system-message { background: #ffc; margin: 10px; padding: 6px 8px; font-size: .8em; }
|
||||||
|
div.system-message p.system-message-title { padding:4px 5px 4px 25px; margin:0; color:red;background:#ffc url(../img/admin/icon_error.gif) 5px .3em no-repeat; }
|
||||||
|
|
||||||
/* PAGE STRUCTURE */
|
/* PAGE STRUCTURE */
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,6 @@
|
||||||
<h3><a href="views/">Views</a></h3>
|
<h3><a href="views/">Views</a></h3>
|
||||||
<p>Each page on the public site is generated by a view. The view defines which template is used to generate the page and which objects are available to that template.</p>
|
<p>Each page on the public site is generated by a view. The view defines which template is used to generate the page and which objects are available to that template.</p>
|
||||||
|
|
||||||
<h3><a href="views/">Views</a></h3>
|
|
||||||
<p>Each page on the public site is generated by a view. The view defines which template is used to generate the page and which objects are available to that template.</p>
|
|
||||||
|
|
||||||
<h3><a href="bookmarklets/">Bookmarklets</a></h3>
|
<h3><a href="bookmarklets/">Bookmarklets</a></h3>
|
||||||
<p>Tools for your browser to quickly access admin functionality.</p>
|
<p>Tools for your browser to quickly access admin functionality.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,37 +10,35 @@
|
||||||
|
|
||||||
<h1>View documentation</h1>
|
<h1>View documentation</h1>
|
||||||
|
|
||||||
<div id="content-main">
|
|
||||||
|
|
||||||
{% regroup views|dictsort:"site_id" by site as views_by_site %}
|
{% regroup views|dictsort:"site_id" by site as views_by_site %}
|
||||||
{% for site_views in views_by_site %}
|
|
||||||
<div class="module">
|
|
||||||
<h2 id="site{{ site_views.grouper.id }}">Views by URL on {{ site_views.grouper.name }}</h2>
|
|
||||||
|
|
||||||
{% for view in site_views.list|dictsort:"url" %}
|
|
||||||
<h3><a href="{{ view.module }}.{{ view.name }}/"/>{{ view.url|escape }}</a></h3>
|
|
||||||
<p class="small quiet">({{ view.module }}.{{ view.name }})</p>
|
|
||||||
<p>{{ view.title }}</p>
|
|
||||||
<hr>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block sidebar %}
|
|
||||||
<div id="content-related" class="sidebar">
|
<div id="content-related" class="sidebar">
|
||||||
<div class="module">
|
<div class="module">
|
||||||
<h2>Jump to site</h2>
|
<h2>Jump to site</h2>
|
||||||
<ul>
|
<ul>
|
||||||
{% regroup views|dictsort:"site_id" by site as views_by_site %}
|
|
||||||
{% for site_views in views_by_site %}
|
{% for site_views in views_by_site %}
|
||||||
<li><a href="#site{{ site_views.grouper.id }}">{{ site_views.grouper.name }}</a></li>
|
<li><a href="#site{{ site_views.grouper.id }}">{{ site_views.grouper.name }}</a></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="content-main">
|
||||||
|
|
||||||
|
{% for site_views in views_by_site %}
|
||||||
|
<div class="module">
|
||||||
|
<h2 id="site{{ site_views.grouper.id }}">Views by URL on {{ site_views.grouper.name }}</h2>
|
||||||
|
|
||||||
|
{% for view in site_views.list|dictsort:"url" %}
|
||||||
|
{% ifchanged %}
|
||||||
|
<h3><a href="{{ view.module }}.{{ view.name }}/"/>{{ view.url|escape }}</a></h3>
|
||||||
|
<p class="small quiet">View function: {{ view.module }}.{{ view.name }}</p>
|
||||||
|
<p>{{ view.title }}</p>
|
||||||
|
<hr>
|
||||||
|
{% endifchanged %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -470,7 +470,9 @@ def do_if(parser, token):
|
||||||
"""
|
"""
|
||||||
The ``{% if %}`` tag evaluates a variable, and if that variable is "true"
|
The ``{% if %}`` tag evaluates a variable, and if that variable is "true"
|
||||||
(i.e. exists, is not empty, and is not a false boolean value) the contents
|
(i.e. exists, is not empty, and is not a false boolean value) the contents
|
||||||
of the block are output::
|
of the block are output:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
{% if althlete_list %}
|
{% if althlete_list %}
|
||||||
Number of athletes: {{ althete_list|count }}
|
Number of athletes: {{ althete_list|count }}
|
||||||
|
@ -481,7 +483,7 @@ def do_if(parser, token):
|
||||||
In the above, if ``athlete_list`` is not empty, the number of athletes will
|
In the above, if ``athlete_list`` is not empty, the number of athletes will
|
||||||
be displayed by the ``{{ athlete_list|count }}`` variable.
|
be displayed by the ``{{ athlete_list|count }}`` variable.
|
||||||
|
|
||||||
As you can see, the ``if`` tag can take an option ``{% else %} clause that
|
As you can see, the ``if`` tag can take an option ``{% else %}`` clause that
|
||||||
will be displayed if the test fails.
|
will be displayed if the test fails.
|
||||||
|
|
||||||
``if`` tags may use ``or`` or ``not`` to test a number of variables or to
|
``if`` tags may use ``or`` or ``not`` to test a number of variables or to
|
||||||
|
@ -501,8 +503,8 @@ def do_if(parser, token):
|
||||||
stupid; it's not my fault).
|
stupid; it's not my fault).
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
For simplicity, ``if`` tags do not allow ``and`` clauses; use nested ``if``s
|
For simplicity, ``if`` tags do not allow ``and`` clauses; use nested ``if``
|
||||||
instead::
|
tags instead::
|
||||||
|
|
||||||
{% if athlete_list %}
|
{% if athlete_list %}
|
||||||
{% if coach_list %}
|
{% if coach_list %}
|
||||||
|
|
|
@ -8,18 +8,7 @@ from email.Errors import HeaderParseError
|
||||||
import docutils.core
|
import docutils.core
|
||||||
import docutils.nodes
|
import docutils.nodes
|
||||||
import docutils.parsers.rst.roles
|
import docutils.parsers.rst.roles
|
||||||
|
from urlparse import urljoin
|
||||||
#
|
|
||||||
# reST roles
|
|
||||||
#
|
|
||||||
ROLES = {
|
|
||||||
# role name, base role url (in the admin)
|
|
||||||
'model' : '/doc/models/%s/',
|
|
||||||
'view' : '/doc/views/%s/',
|
|
||||||
'template' : '/doc/templates/%s/',
|
|
||||||
'filter' : '/doc/filters/#%s',
|
|
||||||
'tag' : '/doc/tags/#%s',
|
|
||||||
}
|
|
||||||
|
|
||||||
def trim_docstring(docstring):
|
def trim_docstring(docstring):
|
||||||
"""
|
"""
|
||||||
|
@ -60,31 +49,43 @@ def parse_docstring(docstring):
|
||||||
body = "\n\n".join(parts[1:])
|
body = "\n\n".join(parts[1:])
|
||||||
return title, body, metadata
|
return title, body, metadata
|
||||||
|
|
||||||
def parse_rst(text, default_reference_context, thing_being_parsed=None):
|
def parse_rst(text, default_reference_context, thing_being_parsed=None, link_base='../..'):
|
||||||
"""
|
"""
|
||||||
Convert the string from reST to an XHTML fragment.
|
Convert the string from reST to an XHTML fragment.
|
||||||
"""
|
"""
|
||||||
overrides = {
|
overrides = {
|
||||||
'input_encoding' : 'unicode',
|
|
||||||
'doctitle_xform' : True,
|
'doctitle_xform' : True,
|
||||||
'inital_header_level' : 3,
|
'inital_header_level' : 3,
|
||||||
|
"default_reference_context" : default_reference_context,
|
||||||
|
"link_base" : link_base,
|
||||||
}
|
}
|
||||||
if thing_being_parsed:
|
if thing_being_parsed:
|
||||||
thing_being_parsed = "<%s>" % thing_being_parsed
|
thing_being_parsed = "<%s>" % thing_being_parsed
|
||||||
parts = docutils.core.publish_parts(text, source_path=thing_being_parsed,
|
parts = docutils.core.publish_parts(text, source_path=thing_being_parsed,
|
||||||
destination_path=None, writer_name='html',
|
destination_path=None, writer_name='html',
|
||||||
settings_overrides={'default_reference_context' : default_reference_context})
|
settings_overrides=overrides)
|
||||||
return parts['fragment']
|
return parts['fragment']
|
||||||
|
|
||||||
|
#
|
||||||
|
# reST roles
|
||||||
|
#
|
||||||
|
ROLES = {
|
||||||
|
'model' : '%s/models/%s/',
|
||||||
|
'view' : '%s/views/%s/',
|
||||||
|
'template' : '%s/templates/%s/',
|
||||||
|
'filter' : '%s/filters/#%s',
|
||||||
|
'tag' : '%s/tags/#%s',
|
||||||
|
}
|
||||||
|
|
||||||
def create_reference_role(rolename, urlbase):
|
def create_reference_role(rolename, urlbase):
|
||||||
def _role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
def _role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||||
node = docutils.nodes.reference(rawtext, text, refuri=(urlbase % text), **options)
|
node = docutils.nodes.reference(rawtext, text, refuri=(urlbase % (inliner.document.settings.link_base, text)), **options)
|
||||||
return [node], []
|
return [node], []
|
||||||
docutils.parsers.rst.roles.register_canonical_role(rolename, _role)
|
docutils.parsers.rst.roles.register_canonical_role(rolename, _role)
|
||||||
|
|
||||||
def default_reference_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
def default_reference_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||||
context = inliner.document.settings.default_reference_context
|
context = inliner.document.settings.default_reference_context
|
||||||
node = docutils.nodes.reference(rawtext, text, refuri=(ROLES[context] % text), **options)
|
node = docutils.nodes.reference(rawtext, text, refuri=(ROLES[context] % (inliner.document.settings.link_base, text)), **options)
|
||||||
return [node], []
|
return [node], []
|
||||||
docutils.parsers.rst.roles.register_canonical_role('cmsreference', default_reference_role)
|
docutils.parsers.rst.roles.register_canonical_role('cmsreference', default_reference_role)
|
||||||
docutils.parsers.rst.roles.DEFAULT_INTERPRETED_ROLE = 'cmsreference'
|
docutils.parsers.rst.roles.DEFAULT_INTERPRETED_ROLE = 'cmsreference'
|
||||||
|
|
|
@ -17,14 +17,20 @@ class AdminLogNode(template.Node):
|
||||||
class DoGetAdminLog:
|
class DoGetAdminLog:
|
||||||
"""
|
"""
|
||||||
Populates a template variable with the admin log for the given criteria.
|
Populates a template variable with the admin log for the given criteria.
|
||||||
Usage:
|
|
||||||
|
Usage::
|
||||||
|
|
||||||
{% get_admin_log [limit] as [varname] for_user [context_var_containing_user_obj] %}
|
{% get_admin_log [limit] as [varname] for_user [context_var_containing_user_obj] %}
|
||||||
Examples:
|
|
||||||
|
Examples::
|
||||||
|
|
||||||
{% get_admin_log 10 as admin_log for_user 23 %}
|
{% get_admin_log 10 as admin_log for_user 23 %}
|
||||||
{% get_admin_log 10 as admin_log for_user user %}
|
{% get_admin_log 10 as admin_log for_user user %}
|
||||||
{% get_admin_log 10 as admin_log %}
|
{% get_admin_log 10 as admin_log %}
|
||||||
Note that [context_var_containing_user_obj] can be a hard-coded integer (user ID) or the
|
|
||||||
name of a template context variable containing the user object whose ID you want.
|
Note that ``context_var_containing_user_obj`` can be a hard-coded integer
|
||||||
|
(user ID) or the name of a template context variable containing the user
|
||||||
|
object whose ID you want.
|
||||||
"""
|
"""
|
||||||
def __init__(self, tag_name):
|
def __init__(self, tag_name):
|
||||||
self.tag_name = tag_name
|
self.tag_name = tag_name
|
||||||
|
|
|
@ -2,7 +2,6 @@ from django.core import meta
|
||||||
from django import templatetags
|
from django import templatetags
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.models.core import sites
|
from django.models.core import sites
|
||||||
from django.views.decorators.cache import cache_page
|
|
||||||
from django.core.extensions import DjangoContext as Context
|
from django.core.extensions import DjangoContext as Context
|
||||||
from django.core.exceptions import Http404, ViewDoesNotExist
|
from django.core.exceptions import Http404, ViewDoesNotExist
|
||||||
from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect
|
from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect
|
||||||
|
@ -32,6 +31,8 @@ def bookmarklets(request):
|
||||||
return HttpResponse(t.render(c))
|
return HttpResponse(t.render(c))
|
||||||
|
|
||||||
def template_tag_index(request):
|
def template_tag_index(request):
|
||||||
|
import sys
|
||||||
|
|
||||||
if not doc:
|
if not doc:
|
||||||
return missing_docutils_page(request)
|
return missing_docutils_page(request)
|
||||||
|
|
||||||
|
@ -69,7 +70,6 @@ def template_tag_index(request):
|
||||||
'tags' : tags,
|
'tags' : tags,
|
||||||
})
|
})
|
||||||
return HttpResponse(t.render(c))
|
return HttpResponse(t.render(c))
|
||||||
template_tag_index = cache_page(template_tag_index, 15*60)
|
|
||||||
|
|
||||||
def template_filter_index(request):
|
def template_filter_index(request):
|
||||||
if not doc:
|
if not doc:
|
||||||
|
@ -106,7 +106,6 @@ def template_filter_index(request):
|
||||||
'filters' : filters,
|
'filters' : filters,
|
||||||
})
|
})
|
||||||
return HttpResponse(t.render(c))
|
return HttpResponse(t.render(c))
|
||||||
template_filter_index = cache_page(template_filter_index, 15*60)
|
|
||||||
|
|
||||||
def view_index(request):
|
def view_index(request):
|
||||||
if not doc:
|
if not doc:
|
||||||
|
@ -118,13 +117,9 @@ def view_index(request):
|
||||||
urlconf = __import__(settings_mod.ROOT_URLCONF, '', '', [''])
|
urlconf = __import__(settings_mod.ROOT_URLCONF, '', '', [''])
|
||||||
view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns)
|
view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns)
|
||||||
for (func, regex) in view_functions:
|
for (func, regex) in view_functions:
|
||||||
title, body, metadata = doc.parse_docstring(func.__doc__)
|
|
||||||
if title:
|
|
||||||
title = doc.parse_rst(title, 'view', 'view:' + func.__name__)
|
|
||||||
views.append({
|
views.append({
|
||||||
'name' : func.__name__,
|
'name' : func.__name__,
|
||||||
'module' : func.__module__,
|
'module' : func.__module__,
|
||||||
'title' : title,
|
|
||||||
'site_id': settings_mod.SITE_ID,
|
'site_id': settings_mod.SITE_ID,
|
||||||
'site' : sites.get_object(pk=settings_mod.SITE_ID),
|
'site' : sites.get_object(pk=settings_mod.SITE_ID),
|
||||||
'url' : simplify_regex(regex),
|
'url' : simplify_regex(regex),
|
||||||
|
@ -134,7 +129,6 @@ def view_index(request):
|
||||||
'views' : views,
|
'views' : views,
|
||||||
})
|
})
|
||||||
return HttpResponse(t.render(c))
|
return HttpResponse(t.render(c))
|
||||||
view_index = cache_page(view_index, 15*60)
|
|
||||||
|
|
||||||
def view_detail(request, view):
|
def view_detail(request, view):
|
||||||
if not doc:
|
if not doc:
|
||||||
|
@ -151,7 +145,7 @@ def view_detail(request, view):
|
||||||
if body:
|
if body:
|
||||||
body = doc.parse_rst(body, 'view', 'view:' + view)
|
body = doc.parse_rst(body, 'view', 'view:' + view)
|
||||||
for key in metadata:
|
for key in metadata:
|
||||||
metadata[key] = doc.parse_rst(metadata[key], 'view', 'view:' + view)
|
metadata[key] = doc.parse_rst(metadata[key], 'model', 'view:' + view)
|
||||||
t = template_loader.get_template('doc/view_detail')
|
t = template_loader.get_template('doc/view_detail')
|
||||||
c = Context(request, {
|
c = Context(request, {
|
||||||
'name' : view,
|
'name' : view,
|
||||||
|
|
Loading…
Reference in New Issue