Ticket #6470: admin-urlpatterns.5.diff

File admin-urlpatterns.5.diff, 17.3 KB (added by Alex Gaynor, 16 years ago)
  • 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..708af25 100644
    a b from django.forms.models import BaseInlineFormSet  
    55from django.contrib.contenttypes.models import ContentType
    66from django.contrib.admin import widgets
    77from django.contrib.admin import helpers
    8 from django.contrib.admin.util import quote, unquote, flatten_fieldsets, get_deleted_objects
     8from django.contrib.admin.util import quote, unquote, flatten_fieldsets, get_deleted_objects, admin_perm_test
    99from django.core.exceptions import PermissionDenied
    1010from django.db import models, transaction
    1111from django.http import Http404, HttpResponse, HttpResponseRedirect
    class ModelAdmin(BaseModelAdmin):  
    196196        else:
    197197            return self.change_view(request, unquote(url))
    198198
     199    def get_urls(self):
     200        from django.conf.urls.defaults import patterns, url
     201        info = self.admin_site.name, self.model._meta.app_label, self.model._meta.module_name
     202        urlpatterns = patterns('',
     203            url(r'^$', lambda *args, **kwargs: self.changelist_view(*args, **kwargs), name='%sadmin_%s_%s_changelist' % info),
     204            url(r'^add/$', lambda *args, **kwargs: self.add_view(*args, **kwargs), name='%sadmin_%s_%s_add' % info),
     205            url(r'^(.+)/history/$', lambda *args, **kwargs: self.history_view(*args, **kwargs), name='%sadmin_%s_%s_history' % info),
     206            url(r'^(.+)/delete/$', lambda *args, **kwargs: self.delete_view(*args, **kwargs), name='%sadmin_%s_%s_delete' % info),
     207            url(r'^(.+)/$', lambda *args, **kwargs: self.change_view(*args, **kwargs), name='%sadmin_%s_%s_change' % info),
     208        )
     209        return urlpatterns
     210
     211    def urls(self):
     212        return self.get_urls()
     213    urls = property(urls)
     214 
     215
    199216    def _media(self):
    200217        from django.conf import settings
    201218
    class ModelAdmin(BaseModelAdmin):  
    537554        }
    538555        context.update(extra_context or {})
    539556        return self.render_change_form(request, context, add=True)
    540     add_view = transaction.commit_on_success(add_view)
     557    add_view = transaction.commit_on_success(admin_perm_test(add_view))
    541558
    542559    def change_view(self, request, object_id, extra_context=None):
    543560        "The 'change' admin view for this model."
    class ModelAdmin(BaseModelAdmin):  
    545562        opts = model._meta
    546563
    547564        try:
    548             obj = model._default_manager.get(pk=object_id)
     565            obj = model._default_manager.get(pk=unquote(object_id))
    549566        except model.DoesNotExist:
    550567            # Don't raise Http404 just yet, because we haven't checked
    551568            # permissions yet. We don't want an unauthenticated user to be able
    class ModelAdmin(BaseModelAdmin):  
    616633        }
    617634        context.update(extra_context or {})
    618635        return self.render_change_form(request, context, change=True, obj=obj)
    619     change_view = transaction.commit_on_success(change_view)
     636    change_view = transaction.commit_on_success(admin_perm_test(change_view))
    620637
    621638    def changelist_view(self, request, extra_context=None):
    622639        "The 'change list' admin view for this model."
    class ModelAdmin(BaseModelAdmin):  
    652669            'admin/%s/change_list.html' % app_label,
    653670            'admin/change_list.html'
    654671        ], context, context_instance=template.RequestContext(request))
     672    changelist_view = admin_perm_test(changelist_view)
    655673
    656674    def delete_view(self, request, object_id, extra_context=None):
    657675        "The 'delete' admin view for this model."
    class ModelAdmin(BaseModelAdmin):  
    659677        app_label = opts.app_label
    660678
    661679        try:
    662             obj = self.model._default_manager.get(pk=object_id)
     680            obj = self.model._default_manager.get(pk=unquote(object_id))
    663681        except self.model.DoesNotExist:
    664682            # Don't raise Http404 just yet, because we haven't checked
    665683            # permissions yet. We don't want an unauthenticated user to be able
    class ModelAdmin(BaseModelAdmin):  
    674692
    675693        # Populate deleted_objects, a data structure of all related objects that
    676694        # 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))), []]
     695        deleted_objects = [mark_safe(u'%s: <a href="../../%s/">%s</a>' % (escape(force_unicode(capfirst(opts.verbose_name))), object_id, escape(obj))), []]
    678696        perms_needed = set()
    679697        get_deleted_objects(deleted_objects, perms_needed, request.user, obj, opts, 1, self.admin_site)
    680698
    class ModelAdmin(BaseModelAdmin):  
    707725            "admin/%s/delete_confirmation.html" % app_label,
    708726            "admin/delete_confirmation.html"
    709727        ], context, context_instance=template.RequestContext(request))
     728    delete_view = admin_perm_test(delete_view)
    710729
    711730    def history_view(self, request, object_id, extra_context=None):
    712731        "The 'history' admin view for this model."
    class ModelAdmin(BaseModelAdmin):  
    734753            "admin/%s/object_history.html" % app_label,
    735754            "admin/object_history.html"
    736755        ], context, context_instance=template.RequestContext(request))
     756    history_view = admin_perm_test(history_view)
    737757
    738758class InlineModelAdmin(BaseModelAdmin):
    739759    """
  • django/contrib/admin/sites.py

    diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py
    index c16ab6a..1b24211 100644
    a b  
    11import base64
    22import re
     3
    34from django import http, template
    45from django.contrib.admin import ModelAdmin
     6from django.contrib.admin.util import admin_perm_test
    57from django.contrib.auth import authenticate, login
    68from django.db.models.base import ModelBase
    79from django.core.exceptions import ImproperlyConfigured
    class AdminSite(object):  
    3436    login_template = None
    3537    app_index_template = None
    3638
    37     def __init__(self):
     39    def __init__(self, name=None):
    3840        self._registry = {} # model_class class -> admin_class instance
     41        # TODO Root path is used to calculate urls under the old root() method
     42        # in order to maintain backwards compatibility we are leaving that in
     43        # so root_path isn't needed, not sure what to do about this.
     44        self.root_path = 'admin/'
     45        if name is None:
     46            name = ''
     47        else:
     48            name += '_'
     49        self.name = name
    3950
    4051    def register(self, model_or_iterable, admin_class=None, **options):
    4152        """
    class AdminSite(object):  
    121132
    122133        `url` is the remainder of the URL -- e.g. 'comments/comment/'.
    123134        """
     135        import warnings
     136        warnings.warn("Using AdminSite.root() is deprecated, you should \
     137            include(AdminSite.urls) instead", PendingDeprecationWarning)
    124138        if request.method == 'GET' and not request.path.endswith('/'):
    125139            return http.HttpResponseRedirect(request.path + '/')
    126140
    class AdminSite(object):  
    159173                return self.app_index(request, url)
    160174
    161175        raise http.Http404('The requested admin page does not exist.')
    162 
     176   
     177    def get_urls(self):
     178        from django.conf.urls.defaults import patterns, url, include
     179        urlpatterns = patterns('',
     180            url(r'^$', lambda *args, **kwargs: self.index(*args, **kwargs), name='%sadmin_index' % self.name),
     181            url(r'^logout/$', lambda *args, **kwargs: self.logout(*args, **kwargs), name='%sadmin_logout'),
     182            url(r'^password_change/$', lambda *args, **kwargs: self.password_change(*args, **kwargs), name='%sadmin_password_change' % self.name),
     183            url(r'^password_change/done/$', lambda *args, **kwargs: self.password_change_done(*args, **kwargs), name='%sadmin_password_change_done' % self.name),
     184            url(r'^jsi18n/$', lambda *args, **kwargs: self.i18n_javascript(*args, **kwargs), name='%sadmin_jsi18n' % self.name),
     185            url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', 'django.views.defaults.shortcut'),
     186            url(r'^(?P<app_label>\w+)/$', lambda *args, **kwargs: self.app_index(*args, **kwargs), name='%sadmin_app_list' % self.name),
     187        )
     188        for model, model_admin in self._registry.iteritems():
     189            urlpatterns += patterns('',
     190                url(r'^%s/%s/' % (model._meta.app_label, model._meta.module_name), include(model_admin.urls))
     191            )
     192        return urlpatterns
     193   
     194    def urls(self):
     195        return self.get_urls()
     196    urls = property(urls)
     197   
    163198    def model_page(self, request, app_label, model_name, rest_of_url=None):
    164199        """
    165200        Handles the model-specific functionality of the admin site, delegating
    class AdminSite(object):  
    183218        from django.contrib.auth.views import password_change
    184219        return password_change(request,
    185220            post_change_redirect='%spassword_change/done/' % self.root_path)
     221    passoword_change = admin_perm_test(password_change)
    186222
    187223    def password_change_done(self, request):
    188224        """
    class AdminSite(object):  
    190226        """
    191227        from django.contrib.auth.views import password_change_done
    192228        return password_change_done(request)
     229    password_change_done = admin_perm_test(password_change_done)
    193230
    194231    def i18n_javascript(self, request):
    195232        """
    class AdminSite(object):  
    203240        else:
    204241            from django.views.i18n import null_javascript_catalog as javascript_catalog
    205242        return javascript_catalog(request, packages='django.conf')
     243    i18n_javascript = admin_perm_test(i18n_javascript)
    206244
    207245    def logout(self, request):
    208246        """
    class AdminSite(object):  
    317355        return render_to_response(self.index_template or 'admin/index.html', context,
    318356            context_instance=template.RequestContext(request)
    319357        )
    320     index = never_cache(index)
     358    index = never_cache(admin_perm_test(index))
    321359
    322360    def display_login_form(self, request, error_message='', extra_context=None):
    323361        request.session.set_test_cookie()
    class AdminSite(object):  
    377415        return render_to_response(self.app_index_template or 'admin/app_index.html', context,
    378416            context_instance=template.RequestContext(request)
    379417        )
     418    app_index = admin_perm_test(app_index)
    380419
    381420# This global object represents the default admin site, for the common case.
    382421# 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/contrib/auth/admin.py

    diff --git a/django/contrib/auth/admin.py b/django/contrib/auth/admin.py
    index 805ca32..ee2db12 100644
    a b class UserAdmin(admin.ModelAdmin):  
    4040        if url.endswith('password'):
    4141            return self.user_change_password(request, url.split('/')[0])
    4242        return super(UserAdmin, self).__call__(request, url)
     43   
     44    def get_urls(self):
     45        from django.conf.urls.defaults import patterns
     46        urlpatterns = super(UserAdmin, self).get_urls()
     47        urlpatterns = patterns('',
     48            (r'^(\d+)/password/$', self.user_change_password)
     49        ) + urlpatterns
     50        return urlpatterns
    4351
    4452    def add_view(self, request):
    4553        # It's an error for a user to have add permission but NOT change
  • 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..13850ce 100644
    a b model instance::  
    632632                instance.save()
    633633            formset.save_m2m()
    634634
     635``get_urls(self)``
     636~~~~~~~~~~~~~~~~~~~
     637
     638The ``get_urls`` method on a ``ModelAdmin`` returns the URLs to be used for
     639that ModelAdmin in the same way as a URLconf.  Therefore you can extend them as
     640documented in :ref:`topics-http-urls`::
     641   
     642    class MyModelAdmin(admin.ModelAdmin):
     643        def get_urls(self):
     644            urlpatterns = super(MyModelAdmin, self).get_urls()
     645            urlpatterns += patterns('',
     646                (r'^my_view/$', self.my_view)
     647            )
     648            return urlpatterns
     649
     650
    635651``ModelAdmin`` media definitions
    636652--------------------------------
    637653
    In this example, we register the default ``AdminSite`` instance  
    10271043    admin.autodiscover()
    10281044
    10291045    urlpatterns = patterns('',
    1030         ('^admin/(.*)', admin.site.root),
     1046        ('^admin/', include(admin.site.urls)),
    10311047    )
    10321048
    10331049Above we used ``admin.autodiscover()`` to automatically load the
    In this example, we register the ``AdminSite`` instance  
    10411057    from myproject.admin import admin_site
    10421058
    10431059    urlpatterns = patterns('',
    1044         ('^myadmin/(.*)', admin_site.root),
     1060        ('^myadmin/', include(admin_site.urls)),
    10451061    )
    10461062
    10471063There is really no need to use autodiscover when using your own ``AdminSite``
    10481064instance since you will likely be importing all the per-app admin.py modules
    10491065in your ``myproject.admin`` module.
    10501066
    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.
    10531067
    10541068Multiple admin sites in the same URLconf
    10551069----------------------------------------
    respectively::  
    10681082    from myproject.admin import basic_site, advanced_site
    10691083
    10701084    urlpatterns = patterns('',
    1071         ('^basic-admin/(.*)', basic_site.root),
    1072         ('^advanced-admin/(.*)', advanced_site.root),
     1085        ('^basic-admin/', include(basic_site.urls)),
     1086        ('^advanced-admin/', include(advanced_site.urls)),
    10731087    )
     1088
     1089Adding views to admin sites
     1090---------------------------
     1091
     1092It possible to add additional views to the admin site in the same way one can
     1093add them to ``ModelAdmins``.  This by using the ``get_urls()`` method on an
     1094AdminSite in the same way as documented on ``ModelAdmins``.
     1095
     1096Protecting Custom ``AdminSite`` and ``ModelAdmin``
     1097--------------------------------------------------
     1098
     1099By default all the views in the Django admin are protected so that only staff
     1100members can access them.  If you add your own views to either a ``ModelAdmin``
     1101or ``AdminSite`` you should ensure that where necessary they are protected in
     1102the same manner.  To do this use the ``admin_perm_test`` decorator provided in
     1103``django.contrib.admin.utils.admin_perm_test``.  It can be used in the same way
     1104as the ``login_requied`` decorator.
     1105
     1106.. note::
     1107    The ``admin_perm_test`` decorator can only be used on methods which are on
     1108    ``ModelAdmins`` or ``AdminSites``, you cannot use it on arbitrary functions.
  • 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