Ticket #10061: admin-urls.10.diff
File admin-urls.10.diff, 17.2 KB (added by , 16 years ago) |
---|
-
django/contrib/admin/options.py
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 8cc27c5..e00bbd6 100644
a b class ModelAdmin(BaseModelAdmin): 233 233 url(r'^add/$', 234 234 wrap(self.add_view), 235 235 name='%sadmin_%s_%s_add' % info), 236 url(r'^( .+)/history/$',236 url(r'^(?P<object_id>.+)/history/$', 237 237 wrap(self.history_view), 238 238 name='%sadmin_%s_%s_history' % info), 239 url(r'^( .+)/delete/$',239 url(r'^(?P<object_id>.+)/delete/$', 240 240 wrap(self.delete_view), 241 241 name='%sadmin_%s_%s_delete' % info), 242 url(r'^( .+)/$',242 url(r'^(?P<object_id>.+)/$', 243 243 wrap(self.change_view), 244 244 name='%sadmin_%s_%s_change' % info), 245 245 ) … … class ModelAdmin(BaseModelAdmin): 593 593 'save_as': self.save_as, 594 594 'save_on_top': self.save_on_top, 595 595 'root_path': self.admin_site.root_path, 596 'admin_site': self.admin_site.name, 596 597 }) 597 598 return render_to_response(self.change_form_template or [ 598 599 "admin/%s/%s/change_form.html" % (app_label, opts.object_name.lower()), … … class ModelAdmin(BaseModelAdmin): 780 781 'errors': helpers.AdminErrorList(form, formsets), 781 782 'root_path': self.admin_site.root_path, 782 783 'app_label': opts.app_label, 784 'admin_site': self.admin_site.name, 783 785 } 784 786 context.update(extra_context or {}) 785 787 return self.render_change_form(request, context, add=True) … … class ModelAdmin(BaseModelAdmin): 868 870 'inline_admin_formsets': inline_admin_formsets, 869 871 'errors': helpers.AdminErrorList(form, formsets), 870 872 'root_path': self.admin_site.root_path, 873 'admin_site': self.admin_site.name, 871 874 'app_label': opts.app_label, 872 875 } 873 876 context.update(extra_context or {}) … … class ModelAdmin(BaseModelAdmin): 958 961 'media': media, 959 962 'has_add_permission': self.has_add_permission(request), 960 963 'root_path': self.admin_site.root_path, 964 'admin_site': self.admin_site.name, 961 965 'app_label': app_label, 962 966 'action_form': action_form, 963 967 'actions_on_top': self.actions_on_top, … … class ModelAdmin(BaseModelAdmin): 1016 1020 "perms_lacking": perms_needed, 1017 1021 "opts": opts, 1018 1022 "root_path": self.admin_site.root_path, 1023 'admin_site': self.admin_site.name, 1019 1024 "app_label": app_label, 1020 1025 } 1021 1026 context.update(extra_context or {}) … … class ModelAdmin(BaseModelAdmin): 1043 1048 'module_name': capfirst(force_unicode(opts.verbose_name_plural)), 1044 1049 'object': obj, 1045 1050 'root_path': self.admin_site.root_path, 1051 'admin_site': self.admin_site.name, 1046 1052 'app_label': app_label, 1047 1053 } 1048 1054 context.update(extra_context or {}) -
django/contrib/admin/sites.py
diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py index 872e4a0..e7bbfed 100644
a b from django import http, template 3 3 from django.contrib.admin import ModelAdmin 4 4 from django.contrib.auth import authenticate, login 5 5 from django.db.models.base import ModelBase 6 from django.core.urlresolvers import reverse 6 7 from django.core.exceptions import ImproperlyConfigured 7 8 from django.shortcuts import render_to_response 8 9 from django.utils.functional import update_wrapper … … class AdminSite(object): 35 36 36 37 def __init__(self, name=None): 37 38 self._registry = {} # model_class class -> admin_class instance 38 # TODO Root path is used to calculate urls under the old root() method 39 # in order to maintain backwards compatibility we are leaving that in 40 # so root_path isn't needed, not sure what to do about this. 41 self.root_path = 'admin/' 39 self.root_path = None 42 40 if name is None: 43 41 name = '' 44 42 else: … … class AdminSite(object): 171 169 name='%sadmin_index' % self.name), 172 170 url(r'^logout/$', 173 171 wrap(self.logout), 174 name='%sadmin_logout' ),172 name='%sadmin_logout' % self.name), 175 173 url(r'^password_change/$', 176 174 wrap(self.password_change), 177 175 name='%sadmin_password_change' % self.name), … … class AdminSite(object): 205 203 Handles the "change password" task -- both form display and validation. 206 204 """ 207 205 from django.contrib.auth.views import password_change 208 return password_change(request, 209 post_change_redirect='%spassword_change/done/' % self.root_path) 206 if self.root_path is not None: 207 url = '%spassword_change/done/' % self.root_path 208 else: 209 url = reverse('%sadmin_password_change_done' % self.name) 210 return password_change(request, post_change_redirect=url) 210 211 211 212 def password_change_done(self, request): 212 213 """ … … class AdminSite(object): 336 337 'title': _('Site administration'), 337 338 'app_list': app_list, 338 339 'root_path': self.root_path, 340 'admin_site': self.name 339 341 } 340 342 context.update(extra_context or {}) 341 343 return render_to_response(self.index_template or 'admin/index.html', context, … … class AdminSite(object): 350 352 'app_path': request.get_full_path(), 351 353 'error_message': error_message, 352 354 'root_path': self.root_path, 355 'admin_site': self.name, 353 356 } 354 357 context.update(extra_context or {}) 355 358 return render_to_response(self.login_template or 'admin/login.html', context, … … class AdminSite(object): 396 399 'title': _('%s administration') % capfirst(app_label), 397 400 'app_list': [app_dict], 398 401 'root_path': self.root_path, 402 'admin_site': self.name, 399 403 } 400 404 context.update(extra_context or {}) 401 405 return render_to_response(self.app_index_template or 'admin/app_index.html', context, -
django/contrib/admin/templates/admin/base.html
diff --git a/django/contrib/admin/templates/admin/base.html b/django/contrib/admin/templates/admin/base.html index e969d1b..623d769 100644
a b 25 25 {% block branding %}{% endblock %} 26 26 </div> 27 27 {% if user.is_authenticated and user.is_staff %} 28 <div id="user-tools">{% trans 'Welcome,' %} <strong>{% firstof user.first_name user.username %}</strong>. {% block userlinks %}{% url django-admindocs-docroot as docsroot %}{% if docsroot %}<a href="{{ docsroot }}">{% trans 'Documentation' %}</a> / {% endif %}<a href="{{ root_path }}password_change/">{% trans 'Change password' %}</a> / <a href="{{ root_path }}logout/">{% trans 'Log out' %}</a>{% endblock %}</div> 28 <div id="user-tools"> 29 {% trans 'Welcome,' %} 30 <strong> 31 {% firstof user.first_name user.username %} 32 </strong>. 33 {% block userlinks %} 34 {% url django-admindocs-docroot as docsroot %} 35 {% if docsroot %} 36 <a href="{{ docsroot }}"> 37 {% trans 'Documentation' %} 38 </a> / 39 {% endif %} 40 {% url admin_site:admin_password_change as password_change_url %} 41 {% if password_change_url %} 42 <a href="{{ password_change_url }}"> 43 {% else %} 44 <a href="{{ root_path }}password_change/"> 45 {% endif %} 46 {% trans 'Change password' %} 47 </a> / 48 {% url admin_site:admin_logout as logout_url %} 49 {% if logout_url %} 50 <a href="{{ logout_url }}"> 51 {% else %} 52 <a href="{{ root_path }}logout/"> 53 {% endif %} 54 {% trans 'Log out' %} 55 </a> 56 {% endblock %} 57 </div> 29 58 {% endif %} 30 59 {% block nav-global %}{% endblock %} 31 60 </div> -
django/contrib/auth/admin.py
diff --git a/django/contrib/auth/admin.py b/django/contrib/auth/admin.py index c5326b7..9a13205 100644
a b class UserAdmin(admin.ModelAdmin): 92 92 'save_as': False, 93 93 'username_help_text': self.model._meta.get_field('username').help_text, 94 94 'root_path': self.admin_site.root_path, 95 'admin_site': self.admin_site.name, 95 96 'app_label': self.model._meta.app_label, 96 97 }, context_instance=template.RequestContext(request)) 97 98 … … class UserAdmin(admin.ModelAdmin): 122 123 'save_as': False, 123 124 'show_save': True, 124 125 'root_path': self.admin_site.root_path, 126 'admin_site': self.admin_site.name, 125 127 }, context_instance=RequestContext(request)) 126 128 127 129 -
django/contrib/comments/views/moderation.py
diff --git a/django/contrib/comments/views/moderation.py b/django/contrib/comments/views/moderation.py index 3334b09..880c6d7 100644
a b from django.core.paginator import Paginator, InvalidPage 7 7 from django.http import Http404 8 8 from django.contrib import comments 9 9 from django.contrib.comments import signals 10 from django.contrib import admin 10 11 11 12 #@login_required 12 13 def flag(request, comment_id, next=None): … … def moderation_queue(request): 185 186 'previous': page - 1, 186 187 'pages': paginator.num_pages, 187 188 'hits' : paginator.count, 188 'page_range' : paginator.page_range 189 'page_range' : paginator.page_range, 190 'admin_site': admin.site.name, 189 191 }, context_instance=template.RequestContext(request)) 190 192 191 193 moderation_queue = permission_required("comments.can_moderate")(moderation_queue) -
django/core/urlresolvers.py
diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py index 6fc5cfc..7e42c9f 100644
a b def resolve(path, urlconf=None): 257 257 return get_resolver(urlconf).resolve(path) 258 258 259 259 def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None): 260 if isinstance(viewname, basestring): 261 viewname = ''.join(viewname.split(':')) 260 262 args = args or [] 261 263 kwargs = kwargs or {} 262 264 if prefix is None: -
django/template/defaulttags.py
diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index c08ecc4..6fb0b7a 100644
a b class URLNode(Node): 359 359 360 360 def render(self, context): 361 361 from django.core.urlresolvers import reverse, NoReverseMatch 362 view_name_parts = [] 363 for part in self.view_name[:-1]: 364 try: 365 view_name_parts.append(Variable(part).resolve(context)) 366 except VariableDoesNotExist: 367 view_name_parts.append(part) 368 view_name_parts.append(self.view_name[-1]) 369 view_name = ':'.join(view_name_parts) 362 370 args = [arg.resolve(context) for arg in self.args] 363 371 kwargs = dict([(smart_str(k,'ascii'), v.resolve(context)) 364 372 for k, v in self.kwargs.items()]) … … class URLNode(Node): 369 377 # {% url ... as var %} construct in which cause return nothing. 370 378 url = '' 371 379 try: 372 url = reverse( self.view_name, args=args, kwargs=kwargs)380 url = reverse(view_name, args=args, kwargs=kwargs) 373 381 except NoReverseMatch: 374 382 project_name = settings.SETTINGS_MODULE.split('.')[0] 375 383 try: 376 url = reverse(project_name + '.' + self.view_name,384 url = reverse(project_name + '.' + view_name, 377 385 args=args, kwargs=kwargs) 378 386 except NoReverseMatch: 379 387 if self.asvar is None: … … def url(parser, token): 1097 1105 raise TemplateSyntaxError("'%s' takes at least one argument" 1098 1106 " (path to a view)" % bits[0]) 1099 1107 viewname = bits[1] 1108 if ':' in viewname: 1109 viewname = viewname.split(':') 1110 else: 1111 viewname = [viewname] 1100 1112 args = [] 1101 1113 kwargs = {} 1102 1114 asvar = None -
docs/ref/contrib/admin/index.txt
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index 0dff313..420ef25 100644
a b It possible to add additional views to the admin site in the same way one can 1235 1235 add them to ``ModelAdmins``. This by using the ``get_urls()`` method on an 1236 1236 AdminSite in the same way as `described above`__ 1237 1237 1238 .. note:: 1239 Any view you render that uses the admin templates, or extends the base 1240 admin template should include in it's context a variable named 1241 ``admin_site`` that contains the ``AdminSite`` instances name, which for 1242 ``AdminSite`` instances exists at ``self.name`` and for ``ModelAdmin`` 1243 instances exists at ``self.admin_site.name``. 1244 1238 1245 __ `get_urls(self)`_ 1246 1247 1248 Reversing Admin URLs 1249 ==================== 1250 1251 .. versionadded :: 1.1 1252 Before Django 1.1 it wasn't possible to reverse admin URLs. In addition 1253 for this to work you need to be using the new Django 1.1 ``include()`` 1254 syntax for setting up admin URLs. 1255 1256 The following are the url names, and parameters for ``AdminSite`` urls, all 1257 url names are prefixed with the ``AdminSite`` instace's name, followed by an 1258 underscore, so if an ``AdminSite`` was named ``"user_admin"`` it's urls names 1259 would be prefixed with ``"user_admin_"``, the default ``AdminSite``'s name is 1260 ``''`` however it's names *do not* have the trailing underscore: 1261 1262 ====================== =============================== ============= 1263 Page URL name Parameters 1264 ====================== =============================== ============= 1265 Index ``admin_index`` 1266 Logout ``admin_logout`` 1267 Password change ``admin_password_change`` 1268 Password change done ``admin_password_change_done`` 1269 i18n javascript ``admin_jsi18n`` 1270 Application index page ``admin_app_list`` ``app_label`` 1271 ====================== =============================== ============= 1272 1273 The remaining urls are for ``ModelAdmin`` instances, these too are all prefixed 1274 with the ``AdminSite``'s name(with the same caviets as the ``Adminsite``, and 1275 ``app_label`` and ``model_name`` are the lowercase versions of the 1276 application's name and the model's name: 1277 1278 ====================== ===================================================== ============= 1279 Page URL name Parameters 1280 ====================== ===================================================== ============= 1281 Changelist ``admin_{{ app_label }}_{{ model_name }}_changelist`` 1282 Add ``admin_{{ app_label }}_{{ model_name }}_add`` 1283 History ``admin_{{ app_label }}_{{ model_name }}_history`` ``object_id`` 1284 Delete ``admin_{{ app_label }}_{{ model_name }}_delete`` ``object_id`` 1285 Change ``admin_{{ app_label }}_{{ model_name }}_change`` ``object_id`` 1286 ====================== ===================================================== ============= 1287 -
tests/regressiontests/admin_views/tests.py
diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py index ce63567..6b32d3b 100644
a b class AdminViewBasicTest(TestCase): 180 180 self.assertRedirects(response, '/test_admin/%s/admin_views/thing/?e=1' % self.urlbit) 181 181 response = self.client.get('/test_admin/%s/admin_views/thing/' % self.urlbit, {'color__id__exact': 'StringNotInteger!'}) 182 182 self.assertRedirects(response, '/test_admin/%s/admin_views/thing/?e=1' % self.urlbit) 183 184 def testLogoutAndPasswordChangeURLs(self): 185 response = self.client.get('/test_admin/%s/admin_views/article/' % self.urlbit) 186 self.failIf('<a href="/test_admin/%s/logout/">' % self.urlbit not in response.content) 187 self.failIf('<a href="/test_admin/%s/password_change/">' % self.urlbit not in response.content) 183 188 184 189 class CustomModelAdminTest(AdminViewBasicTest): 185 190 urlbit = "admin2" -
tests/urls.py
diff --git a/tests/urls.py b/tests/urls.py index 6704829..31faea5 100644
a b urlpatterns = patterns('', 21 21 # test urlconf for middleware tests 22 22 (r'^middleware/', include('regressiontests.middleware.urls')), 23 23 24 # admin widget tests 25 (r'widget_admin/', include('regressiontests.admin_widgets.urls')), 26 24 27 # admin view tests 25 28 (r'^test_admin/', include('regressiontests.admin_views.urls')), 26 29 (r'^generic_inline_admin/', include('regressiontests.generic_inline_admin.urls')), 27 30 28 # admin widget tests29 (r'widget_admin/', include('regressiontests.admin_widgets.urls')),30 31 31 32 (r'^utils/', include('regressiontests.utils.urls')), 32 33