Ticket #6470: admin-urlpatterns.diff

File admin-urlpatterns.diff, 15.9 KB (added by Alex Gaynor, 16 years ago)

up to date version of the patch

  • django/conf/project_template/urls.py

    diff --git a/django/conf/project_template/urls.py b/django/conf/project_template/urls.py
    index af1d1db..dfb49d3 100644
    a b urlpatterns = patterns('',  
    1313    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
    1414
    1515    # Uncomment the next line to enable the admin:
    16     # (r'^admin/(.*)', admin.site.root),
     16    # (r'^admin/', include(admin.site.urls)),
    1717)
  • django/contrib/admin/options.py

    diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
    index 3d60b9d..966e96c 100644
    a b  
     1import types
     2
    13from django import forms, template
    24from django.forms.formsets import all_valid
    35from django.forms.models import modelform_factory, inlineformset_factory
    from django.forms.models import BaseInlineFormSet  
    57from django.contrib.contenttypes.models import ContentType
    68from django.contrib.admin import widgets
    79from django.contrib.admin import helpers
    8 from django.contrib.admin.util import quote, unquote, flatten_fieldsets, get_deleted_objects
     10from django.contrib.admin.util import quote, unquote, flatten_fieldsets, get_deleted_objects, admin_perm_test
    911from django.core.exceptions import PermissionDenied
    1012from django.db import models, transaction
    1113from django.http import Http404, HttpResponse, HttpResponseRedirect
    class ModelAdmin(BaseModelAdmin):  
    196198        else:
    197199            return self.change_view(request, unquote(url))
    198200
     201    def _get_urls(self):
     202        from django.conf.urls.defaults import patterns, url
     203        urls_module = types.ModuleType('%s.urls' % self.__class__.__name__)
     204        info = self.admin_site.name, self.model._meta.app_label, self.model._meta.module_name
     205        urlpatterns = patterns('',
     206            url(r'^$', lambda *args, **kwargs: self.changelist_view(*args, **kwargs), name='%sadmin_%s_%s_changelist' % info),
     207            url(r'^add/$', lambda *args, **kwargs: self.add_view(*args, **kwargs), name='%sadmin_%s_%s_add' % info),
     208            url(r'^(.+)/history/$', lambda *args, **kwargs: self.history_view(*args, **kwargs), name='%sadmin_%s_%s_history' % info),
     209            url(r'^(.+)/delete/$', lambda *args, **kwargs: self.delete_view(*args, **kwargs), name='%sadmin_%s_%s_delete' % info),
     210            url(r'^(.+)/$', lambda *args, **kwargs: self.change_view(*args, **kwargs), name='%sadmin_%s_%s_change' % info),
     211        )
     212        urls_module.urlpatterns = urlpatterns
     213        return urls_module
     214    urls = property(_get_urls)
     215 
     216
    199217    def _media(self):
    200218        from django.conf import settings
    201219
    class ModelAdmin(BaseModelAdmin):  
    537555        }
    538556        context.update(extra_context or {})
    539557        return self.render_change_form(request, context, add=True)
    540     add_view = transaction.commit_on_success(add_view)
     558    add_view = transaction.commit_on_success(admin_perm_test(add_view))
    541559
    542560    def change_view(self, request, object_id, extra_context=None):
    543561        "The 'change' admin view for this model."
    class ModelAdmin(BaseModelAdmin):  
    545563        opts = model._meta
    546564
    547565        try:
    548             obj = model._default_manager.get(pk=object_id)
     566            obj = model._default_manager.get(pk=unquote(object_id))
    549567        except model.DoesNotExist:
    550568            # Don't raise Http404 just yet, because we haven't checked
    551569            # permissions yet. We don't want an unauthenticated user to be able
    class ModelAdmin(BaseModelAdmin):  
    616634        }
    617635        context.update(extra_context or {})
    618636        return self.render_change_form(request, context, change=True, obj=obj)
    619     change_view = transaction.commit_on_success(change_view)
     637    change_view = transaction.commit_on_success(admin_perm_test(change_view))
    620638
    621639    def changelist_view(self, request, extra_context=None):
    622640        "The 'change list' admin view for this model."
    class ModelAdmin(BaseModelAdmin):  
    652670            'admin/%s/change_list.html' % app_label,
    653671            'admin/change_list.html'
    654672        ], context, context_instance=template.RequestContext(request))
     673    changelist_view = admin_perm_test(changelist_view)
    655674
    656675    def delete_view(self, request, object_id, extra_context=None):
    657676        "The 'delete' admin view for this model."
    class ModelAdmin(BaseModelAdmin):  
    659678        app_label = opts.app_label
    660679
    661680        try:
    662             obj = self.model._default_manager.get(pk=object_id)
     681            obj = self.model._default_manager.get(pk=unquote(object_id))
    663682        except self.model.DoesNotExist:
    664683            # Don't raise Http404 just yet, because we haven't checked
    665684            # permissions yet. We don't want an unauthenticated user to be able
    class ModelAdmin(BaseModelAdmin):  
    674693
    675694        # Populate deleted_objects, a data structure of all related objects that
    676695        # will also be deleted.
    677         deleted_objects = [mark_safe(u'%s: <a href="../../%s/">%s</a>' % (escape(force_unicode(capfirst(opts.verbose_name))), quote(object_id), escape(obj))), []]
     696        deleted_objects = [mark_safe(u'%s: <a href="../../%s/">%s</a>' % (escape(force_unicode(capfirst(opts.verbose_name))), object_id, escape(obj))), []]
    678697        perms_needed = set()
    679698        get_deleted_objects(deleted_objects, perms_needed, request.user, obj, opts, 1, self.admin_site)
    680699
    class ModelAdmin(BaseModelAdmin):  
    707726            "admin/%s/delete_confirmation.html" % app_label,
    708727            "admin/delete_confirmation.html"
    709728        ], context, context_instance=template.RequestContext(request))
     729    delete_view = admin_perm_test(delete_view)
    710730
    711731    def history_view(self, request, object_id, extra_context=None):
    712732        "The 'history' admin view for this model."
    class ModelAdmin(BaseModelAdmin):  
    734754            "admin/%s/object_history.html" % app_label,
    735755            "admin/object_history.html"
    736756        ], context, context_instance=template.RequestContext(request))
     757    history_view = admin_perm_test(history_view)
    737758
    738759class InlineModelAdmin(BaseModelAdmin):
    739760    """
  • django/contrib/admin/sites.py

    diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py
    index c16ab6a..e7bd225 100644
    a b  
    11import base64
    22import re
     3import types
     4
    35from django import http, template
    46from django.contrib.admin import ModelAdmin
     7from django.contrib.admin.util import admin_perm_test
    58from django.contrib.auth import authenticate, login
    69from django.db.models.base import ModelBase
    710from django.core.exceptions import ImproperlyConfigured
    class AdminSite(object):  
    3437    login_template = None
    3538    app_index_template = None
    3639
    37     def __init__(self):
     40    def __init__(self, name=None):
    3841        self._registry = {} # model_class class -> admin_class instance
     42        # TODO Root path is used to calculate urls under the old root() method
     43        # in order to maintain backwards compatibility we are leaving that in
     44        # so root_path isn't needed, not sure what to do about this.
     45        self.root_path = 'admin/'
     46        if name is None:
     47            name = ''
     48        else:
     49            name += '_'
     50        self.name = name
    3951
    4052    def register(self, model_or_iterable, admin_class=None, **options):
    4153        """
    class AdminSite(object):  
    121133
    122134        `url` is the remainder of the URL -- e.g. 'comments/comment/'.
    123135        """
     136        import warnings
     137        warnings.warn("Using AdminSite.root() is deprecated, you should \
     138            include(AdminSite.urls) instead", PendingDeprecationWarning)
    124139        if request.method == 'GET' and not request.path.endswith('/'):
    125140            return http.HttpResponseRedirect(request.path + '/')
    126141
    class AdminSite(object):  
    159174                return self.app_index(request, url)
    160175
    161176        raise http.Http404('The requested admin page does not exist.')
    162 
     177   
     178    def _get_urls(self):
     179        from django.conf.urls.defaults import patterns, url, include
     180        from django.core.urlresolvers import RegexURLResolver
     181        urls_module = types.ModuleType('%s.urls' % self.__class__.__name__)
     182        urlpatterns = patterns('',
     183            url(r'^$', lambda *args, **kwargs: self.index(*args, **kwargs), name='%sadmin_index' % self.name),
     184            url(r'^logout/$', lambda *args, **kwargs: self.logout(*args, **kwargs), name='%sadmin_logout'),
     185            url(r'^password_change/$', lambda *args, **kwargs: self.password_change(*args, **kwargs), name='%sadmin_password_change' % self.name),
     186            url(r'^password_change/done/$', lambda *args, **kwargs: self.password_change_done(*args, **kwargs), name='%sadmin_password_change_done' % self.name),
     187            url(r'^jsi18n/$', lambda *args, **kwargs: self.i18n_javascript(*args, **kwargs), name='%sadmin_jsi18n' % self.name),
     188            url('^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', 'django.views.defaults.shortcut'),
     189            url('^(?P<app_label>\w+)/$', lambda *args, **kwargs: self.app_index(*args, **kwargs), name='%sadmin_app_list' % self.name),
     190        )
     191        for model, model_admin in self._registry.iteritems():
     192            urlpatterns += patterns('',
     193                url('^%s/%s/' % (model._meta.app_label, model._meta.module_name), include(model_admin.urls))
     194            )
     195        urls_module.urlpatterns = urlpatterns
     196        return urls_module
     197    urls = property(_get_urls)
     198   
    163199    def model_page(self, request, app_label, model_name, rest_of_url=None):
    164200        """
    165201        Handles the model-specific functionality of the admin site, delegating
    class AdminSite(object):  
    183219        from django.contrib.auth.views import password_change
    184220        return password_change(request,
    185221            post_change_redirect='%spassword_change/done/' % self.root_path)
     222    passoword_change = admin_perm_test(password_change)
    186223
    187224    def password_change_done(self, request):
    188225        """
    class AdminSite(object):  
    190227        """
    191228        from django.contrib.auth.views import password_change_done
    192229        return password_change_done(request)
     230    password_change_done = admin_perm_test(password_change_done)
    193231
    194232    def i18n_javascript(self, request):
    195233        """
    class AdminSite(object):  
    203241        else:
    204242            from django.views.i18n import null_javascript_catalog as javascript_catalog
    205243        return javascript_catalog(request, packages='django.conf')
     244    i18n_javascript = admin_perm_test(i18n_javascript)
    206245
    207246    def logout(self, request):
    208247        """
    class AdminSite(object):  
    317356        return render_to_response(self.index_template or 'admin/index.html', context,
    318357            context_instance=template.RequestContext(request)
    319358        )
    320     index = never_cache(index)
     359    index = never_cache(admin_perm_test(index))
    321360
    322361    def display_login_form(self, request, error_message='', extra_context=None):
    323362        request.session.set_test_cookie()
    class AdminSite(object):  
    377416        return render_to_response(self.app_index_template or 'admin/app_index.html', context,
    378417            context_instance=template.RequestContext(request)
    379418        )
     419    app_index = admin_perm_test(app_index)
    380420
    381421# This global object represents the default admin site, for the common case.
    382422# You can instantiate AdminSite in your own code to create a custom admin site.
  • django/contrib/admin/util.py

    diff --git a/django/contrib/admin/util.py b/django/contrib/admin/util.py
    index 0900b4e..6b34c78 100644
    a b from django.utils.text import capfirst  
    66from django.utils.encoding import force_unicode
    77from django.utils.translation import ugettext as _
    88
     9def admin_perm_test(func):
     10    def inner(admin_site_or_modeladmin, request, *args, **kwargs):
     11        if hasattr(admin_site_or_modeladmin, 'has_permission'):
     12            admin_site = admin_site_or_modeladmin
     13        else:
     14            admin_site = admin_site_or_modeladmin.admin_site
     15        if not admin_site.has_permission(request):
     16            return admin_site.login(request)
     17        # User has right permisssions show the view
     18        return func(admin_site_or_modeladmin, request, *args, **kwargs)
     19    return inner
    920
    1021def quote(s):
    1122    """
  • django/core/urlresolvers.py

    diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
    index 774e6d3..897cde2 100644
    a b class RegexURLResolver(object):  
    143143        # urlconf_name is a string representing the module containing urlconfs.
    144144        self.regex = re.compile(regex, re.UNICODE)
    145145        self.urlconf_name = urlconf_name
     146        if not isinstance(self.urlconf_name, basestring):
     147            self._urlconf_module = self.urlconf_name
    146148        self.callback = None
    147149        self.default_kwargs = default_kwargs or {}
    148150        self._reverse_dict = MultiValueDict()
  • docs/intro/tutorial02.txt

    diff --git a/docs/intro/tutorial02.txt b/docs/intro/tutorial02.txt
    index 1144167..fb6794b 100644
    a b activate the admin site for your installation, do these three things:  
    5757              # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
    5858
    5959              # Uncomment the next line to enable the admin:
    60               **(r'^admin/(.*)', admin.site.root),**
     60              **(r'^admin/', include(admin.site.urls)),**
    6161          )
    6262
    6363      (The bold lines are the ones that needed to be uncommented.)
  • docs/ref/contrib/admin.txt

    diff --git a/docs/ref/contrib/admin.txt b/docs/ref/contrib/admin.txt
    index f24dc46..f80754d 100644
    a b In this example, we register the default ``AdminSite`` instance  
    10271027    admin.autodiscover()
    10281028
    10291029    urlpatterns = patterns('',
    1030         ('^admin/(.*)', admin.site.root),
     1030        ('^admin/', include(admin.site.urls)),
    10311031    )
    10321032
    10331033Above we used ``admin.autodiscover()`` to automatically load the
    In this example, we register the ``AdminSite`` instance  
    10411041    from myproject.admin import admin_site
    10421042
    10431043    urlpatterns = patterns('',
    1044         ('^myadmin/(.*)', admin_site.root),
     1044        ('^myadmin/', include(admin_site.urls)),
    10451045    )
    10461046
    10471047There is really no need to use autodiscover when using your own ``AdminSite``
    10481048instance since you will likely be importing all the per-app admin.py modules
    10491049in your ``myproject.admin`` module.
    10501050
    1051 Note that the regular expression in the URLpattern *must* group everything in
    1052 the URL that comes after the URL root -- hence the ``(.*)`` in these examples.
    10531051
    10541052Multiple admin sites in the same URLconf
    10551053----------------------------------------
    respectively::  
    10681066    from myproject.admin import basic_site, advanced_site
    10691067
    10701068    urlpatterns = patterns('',
    1071         ('^basic-admin/(.*)', basic_site.root),
    1072         ('^advanced-admin/(.*)', advanced_site.root),
     1069        ('^basic-admin/', include(basic_site.root)),
     1070        ('^advanced-admin/', include(advanced_site.root)),
    10731071    )
  • tests/regressiontests/admin_views/tests.py

    diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
    index 391d1ff..8fb8ad8 100644
    a b class AdminViewBasicTest(TestCase):  
    2626        """
    2727        request = self.client.get('/test_admin/admin/admin_views/article/add')
    2828        self.assertRedirects(request,
    29             '/test_admin/admin/admin_views/article/add/'
     29            '/test_admin/admin/admin_views/article/add/', status_code=301
    3030        )
    3131   
    3232    def testBasicAddGet(self):
  • tests/regressiontests/admin_views/urls.py

    diff --git a/tests/regressiontests/admin_views/urls.py b/tests/regressiontests/admin_views/urls.py
    index 4e5da48..02e0286 100644
    a b import views  
    55urlpatterns = patterns('',
    66    (r'^admin/doc/', include('django.contrib.admindocs.urls')),
    77    (r'^admin/secure-view/$', views.secure_view),
    8     (r'^admin/(.*)', admin.site.root),
     8    (r'^admin/', include(admin.site.urls)),
    99)
Back to Top