Permalink
Browse files

Converted internal link generation in the admin and admin document ge…

…nerator to use named URLs.

Thanks to Florian Apolloner for both the initial patch and his final push to get
this fixed, to Dario Ocles for his great work on the admin templates and
switching the admin_doc application to also use named URLs, to Mikko Hellsing
for his comments and to Jannis and Julien for their review and design guidance.

Fixes #15294.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16857 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
1 parent 7b21bfc commit aaf77c1676e44019abe544911ff7a06eb2690295 @ramiro ramiro committed Sep 20, 2011
Showing with 489 additions and 105 deletions.
  1. +32 −10 django/contrib/admin/options.py
  2. +7 −3 django/contrib/admin/sites.py
  3. +7 −1 django/contrib/admin/templates/admin/500.html
  4. +11 −9 django/contrib/admin/templates/admin/app_index.html
  5. +11 −8 django/contrib/admin/templates/admin/auth/user/change_password.html
  6. +8 −5 django/contrib/admin/templates/admin/base.html
  7. +9 −7 django/contrib/admin/templates/admin/change_form.html
  8. +10 −14 django/contrib/admin/templates/admin/change_list.html
  9. +7 −5 django/contrib/admin/templates/admin/delete_confirmation.html
  10. +6 −4 django/contrib/admin/templates/admin/delete_selected_confirmation.html
  11. +1 −1 django/contrib/admin/templates/admin/index.html
  12. +7 −1 django/contrib/admin/templates/admin/invalid_setup.html
  13. +7 −5 django/contrib/admin/templates/admin/object_history.html
  14. +3 −2 django/contrib/admin/templates/registration/logged_out.html
  15. +7 −2 django/contrib/admin/templates/registration/password_change_done.html
  16. +7 −2 django/contrib/admin/templates/registration/password_change_form.html
  17. +7 −1 django/contrib/admin/templates/registration/password_reset_complete.html
  18. +7 −1 django/contrib/admin/templates/registration/password_reset_confirm.html
  19. +7 −1 django/contrib/admin/templates/registration/password_reset_done.html
  20. +7 −1 django/contrib/admin/templates/registration/password_reset_form.html
  21. +8 −0 django/contrib/admin/templatetags/admin_urls.py
  22. +10 −2 django/contrib/admindocs/templates/admin_doc/bookmarklets.html
  23. +8 −1 django/contrib/admindocs/templates/admin_doc/index.html
  24. +7 −1 django/contrib/admindocs/templates/admin_doc/missing_docutils.html
  25. +11 −2 django/contrib/admindocs/templates/admin_doc/model_detail.html
  26. +11 −2 django/contrib/admindocs/templates/admin_doc/model_index.html
  27. +11 −2 django/contrib/admindocs/templates/admin_doc/template_detail.html
  28. +9 −1 django/contrib/admindocs/templates/admin_doc/template_filter_index.html
  29. +9 −1 django/contrib/admindocs/templates/admin_doc/template_tag_index.html
  30. +11 −2 django/contrib/admindocs/templates/admin_doc/view_detail.html
  31. +11 −3 django/contrib/admindocs/templates/admin_doc/view_index.html
  32. +1 −2 django/contrib/admindocs/views.py
  33. +15 −0 docs/ref/contrib/admin/index.txt
  34. +1 −0 tests/regressiontests/admin_custom_urls/__init__.py
  35. +44 −0 tests/regressiontests/admin_custom_urls/fixtures/actions.json
  36. +20 −0 tests/regressiontests/admin_custom_urls/fixtures/users.json
  37. +50 −0 tests/regressiontests/admin_custom_urls/models.py
  38. +72 −0 tests/regressiontests/admin_custom_urls/tests.py
  39. +7 −0 tests/regressiontests/admin_custom_urls/urls.py
  40. +2 −2 tests/regressiontests/admin_views/tests.py
  41. +3 −1 tests/urls.py
@@ -11,6 +11,7 @@
from django.views.decorators.csrf import csrf_protect
from django.core.exceptions import PermissionDenied, ValidationError
from django.core.paginator import Paginator
+from django.core.urlresolvers import reverse
from django.db import models, transaction, router
from django.db.models.related import RelatedObject
from django.db.models.fields import BLANK_CHOICE_DASH, FieldDoesNotExist
@@ -776,9 +777,12 @@ def response_add(self, request, obj, post_url_continue='../%s/'):
# redirect to the change-list page for this object. Otherwise,
# redirect to the admin index.
if self.has_change_permission(request, None):
- post_url = '../'
+ post_url = reverse('admin:%s_%s_changelist' %
+ (opts.app_label, opts.module_name),
+ current_app=self.admin_site.name)
else:
- post_url = '../../../'
+ post_url = reverse('admin:index',
+ current_app=self.admin_site.name)
return HttpResponseRedirect(post_url)
def response_change(self, request, obj):
@@ -787,11 +791,14 @@ def response_change(self, request, obj):
"""
opts = obj._meta
- # Handle proxy models automatically created by .only() or .defer()
+ # Handle proxy models automatically created by .only() or .defer().
+ # Refs #14529
verbose_name = opts.verbose_name
+ module_name = opts.module_name
if obj._deferred:
opts_ = opts.proxy_for_model._meta
verbose_name = opts_.verbose_name
+ module_name = opts_.module_name
pk_value = obj._get_pk_val()
@@ -805,19 +812,28 @@ def response_change(self, request, obj):
elif "_saveasnew" in request.POST:
msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': force_unicode(verbose_name), 'obj': obj}
self.message_user(request, msg)
- return HttpResponseRedirect("../%s/" % pk_value)
+ return HttpResponseRedirect(reverse('admin:%s_%s_change' %
+ (opts.app_label, module_name),
+ args=(pk_value,),
+ current_app=self.admin_site.name))
elif "_addanother" in request.POST:
self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_unicode(verbose_name)))
- return HttpResponseRedirect("../add/")
+ return HttpResponseRedirect(reverse('admin:%s_%s_add' %
+ (opts.app_label, module_name),
+ current_app=self.admin_site.name))
else:
self.message_user(request, msg)
# Figure out where to redirect. If the user has change permission,
# redirect to the change-list page for this object. Otherwise,
# redirect to the admin index.
if self.has_change_permission(request, None):
- return HttpResponseRedirect('../')
+ post_url = reverse('admin:%s_%s_changelist' %
+ (opts.app_label, module_name),
+ current_app=self.admin_site.name)
else:
- return HttpResponseRedirect('../../../')
+ post_url = reverse('admin:index',
+ current_app=self.admin_site.name)
+ return HttpResponseRedirect(post_url)
def response_action(self, request, queryset):
"""
@@ -990,7 +1006,9 @@ def change_view(self, request, object_id, extra_context=None):
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {'name': force_unicode(opts.verbose_name), 'key': escape(object_id)})
if request.method == 'POST' and "_saveasnew" in request.POST:
- return self.add_view(request, form_url='../add/')
+ return self.add_view(request, form_url=reverse('admin:%s_%s_add' %
+ (opts.app_label, opts.module_name),
+ current_app=self.admin_site.name))
ModelForm = self.get_form(request, obj)
formsets = []
@@ -1246,8 +1264,11 @@ def delete_view(self, request, object_id, extra_context=None):
self.message_user(request, _('The %(name)s "%(obj)s" was deleted successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(obj_display)})
if not self.has_change_permission(request, None):
- return HttpResponseRedirect("../../../../")
- return HttpResponseRedirect("../../")
+ return HttpResponseRedirect(reverse('admin:index',
+ current_app=self.admin_site.name))
+ return HttpResponseRedirect(reverse('admin:%s_%s_changelist' %
+ (opts.app_label, opts.module_name),
+ current_app=self.admin_site.name))
object_name = force_unicode(opts.verbose_name)
@@ -1292,6 +1313,7 @@ def history_view(self, request, object_id, extra_context=None):
'module_name': capfirst(force_unicode(opts.verbose_name_plural)),
'object': obj,
'app_label': app_label,
+ 'opts': opts,
}
context.update(extra_context or {})
return TemplateResponse(request, self.object_history_template or [
@@ -339,17 +339,19 @@ def index(self, request, extra_context=None):
# Check whether user has any perm for this module.
# If so, add the module to the model_list.
if True in perms.values():
+ info = (app_label, model._meta.module_name)
model_dict = {
'name': capfirst(model._meta.verbose_name_plural),
- 'admin_url': mark_safe('%s/%s/' % (app_label, model.__name__.lower())),
+ 'admin_url': reverse('admin:%s_%s_changelist' % info, current_app=self.name),
+ 'add_url': reverse('admin:%s_%s_add' % info, current_app=self.name),
'perms': perms,
}
if app_label in app_dict:
app_dict[app_label]['models'].append(model_dict)
else:
app_dict[app_label] = {
'name': app_label.title(),
- 'app_url': app_label + '/',
+ 'app_url': reverse('admin:app_list', kwargs={'app_label': app_label}, current_app=self.name),
'has_module_perms': has_module_perms,
'models': [model_dict],
}
@@ -383,9 +385,11 @@ def app_index(self, request, app_label, extra_context=None):
# Check whether user has any perm for this module.
# If so, add the module to the model_list.
if True in perms.values():
+ info = (app_label, model._meta.module_name)
model_dict = {
'name': capfirst(model._meta.verbose_name_plural),
- 'admin_url': '%s/' % model.__name__.lower(),
+ 'admin_url': reverse('admin:%s_%s_changelist' % info, current_app=self.name),
+ 'add_url': reverse('admin:%s_%s_add' % info, current_app=self.name),
'perms': perms,
}
if app_dict:
@@ -1,7 +1,13 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
+{% load url from future %}
-{% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans "Home" %}</a> &rsaquo; {% trans "Server error" %}</div>{% endblock %}
+{% block breadcrumbs %}
+<div class="breadcrumbs">
+<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
+&rsaquo; {% trans 'Server error' %}
+</div>
+{% endblock %}
{% block title %}{% trans 'Server error (500)' %}{% endblock %}
@@ -1,15 +1,17 @@
-{% extends "admin/index.html" %}
-{% load i18n %}
+{% extends "admin/index.html" %}
+{% load i18n %}
+{% load url from future %}
{% if not is_popup %}
-
{% block breadcrumbs %}
-<div class="breadcrumbs"><a href="../">
-{% trans "Home" %}</a> &rsaquo;
+<div class="breadcrumbs">
+<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
+&rsaquo;
{% for app in app_list %}
{% blocktrans with app.name as name %}{{ name }}{% endblocktrans %}
-{% endfor %}</div>{% endblock %}
-
-{% endif %}
+{% endfor %}
+</div>
+{% endblock %}
+{% endif %}
-{% block sidebar %}{% endblock %}
+{% block sidebar %}{% endblock %}
@@ -1,21 +1,24 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_static admin_modify %}
{% load url from future %}
+{% load admin_urls %}
+
{% block extrahead %}{{ block.super }}
{% url 'admin:jsi18n' as jsi18nurl %}
<script type="text/javascript" src="{{ jsi18nurl|default:"../../../../jsi18n/" }}"></script>
{% endblock %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
{% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% endblock %}
-{% block breadcrumbs %}{% if not is_popup %}
-<div class="breadcrumbs">
- <a href="../../../../">{% trans "Home" %}</a> &rsaquo;
- <a href="../../../">{{ opts.app_label|capfirst|escape }}</a> &rsaquo;
- <a href="../../">{{ opts.verbose_name_plural|capfirst }}</a> &rsaquo;
- <a href="../">{{ original|truncatewords:"18" }}</a> &rsaquo;
- {% trans 'Change password' %}
+{% if not is_popup %}
+{% block breadcrumbs %}
+<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
+&rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_label|capfirst|escape }}</a>
+&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
+&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}{{ original.pk }}">{{ original|truncatewords:"18" }}</a>
+&rsaquo; {% trans 'Change password' %}
</div>
-{% endif %}{% endblock %}
+{% endblock %}
+{% endif %}
{% block content %}<div id="content-main">
<form action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% csrf_token %}{% block form_top %}{% endblock %}
<div>
@@ -32,17 +32,20 @@
{% if docsroot %}
<a href="{{ docsroot }}">{% trans 'Documentation' %}</a> /
{% endif %}
- <a href="{% url 'admin:password_change' %}">
- {% trans 'Change password' %}</a> /
- <a href="{% url 'admin:logout' %}">
- {% trans 'Log out' %}</a>
+ <a href="{% url 'admin:password_change' %}">{% trans 'Change password' %}</a> /
+ <a href="{% url 'admin:logout' %}">{% trans 'Log out' %}</a>
{% endblock %}
</div>
{% endif %}
{% block nav-global %}{% endblock %}
</div>
<!-- END Header -->
- {% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} &rsaquo; {{ title }}{% endif %}</div>{% endblock %}
+ {% block breadcrumbs %}
+ <div class="breadcrumbs">
+ <a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
+ {% if title %} &rsaquo; {{ title }}{% endif %}
+ </div>
+ {% endblock %}
{% endif %}
{% block messages %}
@@ -1,6 +1,7 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_static admin_modify %}
{% load url from future %}
+{% load admin_urls %}
{% block extrahead %}{{ block.super }}
{% url 'admin:jsi18n' as jsi18nurl %}
@@ -14,14 +15,15 @@
{% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% endblock %}
-{% block breadcrumbs %}{% if not is_popup %}
-<div class="breadcrumbs">
- <a href="../../../">{% trans "Home" %}</a> &rsaquo;
- <a href="../../">{{ app_label|capfirst|escape }}</a> &rsaquo;
- {% if has_change_permission %}<a href="../">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %} &rsaquo;
- {% if add %}{% trans "Add" %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18" }}{% endif %}
+{% if not is_popup %}
+{% block breadcrumbs %}
+<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
+&rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ app_label|capfirst|escape }}</a>
+&rsaquo; {% if has_change_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
+&rsaquo; {% if add %}{% trans 'Add' %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18" }}{% endif %}
</div>
-{% endif %}{% endblock %}
+{% endblock %}
+{% endif %}
{% block content %}<div id="content-main">
{% block object-tools %}
@@ -1,6 +1,8 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_static admin_list %}
{% load url from future %}
+{% load admin_urls %}
+
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static "admin/css/changelists.css" %}" />
@@ -36,19 +38,13 @@
{% block bodyclass %}change-list{% endblock %}
{% if not is_popup %}
- {% block breadcrumbs %}
- <div class="breadcrumbs">
- <a href="../../">
- {% trans "Home" %}
- </a>
- &rsaquo;
- <a href="../">
- {{ app_label|capfirst }}
- </a>
- &rsaquo;
- {{ cl.opts.verbose_name_plural|capfirst }}
- </div>
- {% endblock %}
+{% block breadcrumbs %}
+<div class="breadcrumbs">
+<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
+&rsaquo; <a href="{% url 'admin:app_list' app_label=cl.opts.app_label %}">{{ app_label|capfirst|escape }}</a>
+&rsaquo; {{ cl.opts.verbose_name_plural|capfirst }}
+</div>
+{% endblock %}
{% endif %}
{% block coltype %}flex{% endblock %}
@@ -60,7 +56,7 @@
<ul class="object-tools">
{% block object-tools-items %}
<li>
- <a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">
+ <a href="{% url cl.opts|admin_urlname:'add' %}{% if is_popup %}?_popup=1{% endif %}" class="addlink">
{% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}
</a>
</li>
@@ -1,13 +1,15 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
+{% load url from future %}
+{% load admin_urls %}
{% block breadcrumbs %}
<div class="breadcrumbs">
- <a href="../../../../">{% trans "Home" %}</a> &rsaquo;
- <a href="../../../">{{ app_label|capfirst }}</a> &rsaquo;
- <a href="../../">{{ opts.verbose_name_plural|capfirst }}</a> &rsaquo;
- <a href="../">{{ object|truncatewords:"18" }}</a> &rsaquo;
- {% trans 'Delete' %}
+<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
+&rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ app_label|capfirst }}</a>
+&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst|escape }}</a>
+&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}{{ object.pk }}">{{ object|truncatewords:"18" }}</a>
+&rsaquo; {% trans 'Delete' %}
</div>
{% endblock %}
@@ -1,12 +1,14 @@
{% extends "admin/base_site.html" %}
{% load i18n l10n %}
+{% load url from future %}
+{% load admin_urls %}
{% block breadcrumbs %}
<div class="breadcrumbs">
- <a href="../../">{% trans "Home" %}</a> &rsaquo;
- <a href="../">{{ app_label|capfirst }}</a> &rsaquo;
- <a href="./">{{ opts.verbose_name_plural|capfirst }}</a> &rsaquo;
- {% trans 'Delete multiple objects' %}
+<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
+&rsaquo; <a href="{% url 'admin:app_list' app_label=app_label %}">{{ app_label|capfirst|escape }}</a>
+&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
+&rsaquo; {% trans 'Delete multiple objects' %}
</div>
{% endblock %}
@@ -26,7 +26,7 @@
{% endif %}
{% if model.perms.add %}
- <td><a href="{{ model.admin_url }}add/" class="addlink">{% trans 'Add' %}</a></td>
+ <td><a href="{{ model.add_url }}" class="addlink">{% trans 'Add' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
@@ -1,7 +1,13 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
+{% load url from future %}
-{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> &rsaquo; {{ title }}</div>{% endblock %}
+{% block breadcrumbs %}
+<div class="breadcrumbs">
+<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
+&rsaquo; {{ title }}
+</div>
+{% endblock %}
{% block content %}
<p>{% trans "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." %}</p>
Oops, something went wrong. Retry.

0 comments on commit aaf77c1

Please sign in to comment.