Ticket #6470: nfa-urls.diff

File nfa-urls.diff, 16.2 KB (added by Alex, 7 years ago)

Initial work on implementing them using a property, not complete(although more or less functional), tests do not all pass

  • django/contrib/admin/options.py

    diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
    index 234cfd1..977199a 100644
    a b from django.utils.text import capfirst, get_text_list 
    1616from django.utils.translation import ugettext as _
    1717from django.utils.encoding import force_unicode
    1818import sets
     19import types
    1920
    2021HORIZONTAL, VERTICAL = 1, 2
    2122# returns the <ul> class for a given radio_admin field
    def flatten_fieldsets(fieldsets): 
    5657                field_names.append(field)
    5758    return field_names
    5859
     60def admin_perm_test(func):
     61    def inner(model_admin, request, *args, **kwargs):
     62        if not model_admin.admin_site.has_permission(request):
     63            response = model_admin.admin_site.login(request)
     64            if response:         
     65                return response
     66        return func(model_admin, request, *args, **kwargs)
     67    return inner
     68
    5969class AdminForm(object):
    6070    def __init__(self, form, fieldsets, prepopulated_fields):
    6171        self.form, self.fieldsets = form, fieldsets
    class ModelAdmin(BaseModelAdmin): 
    265275                raise ImproperlyConfigured("Put 'django.contrib.contenttypes' in your INSTALLED_APPS setting in order to use the admin application.")
    266276            if 'django.core.context_processors.auth' not in settings.TEMPLATE_CONTEXT_PROCESSORS:
    267277                raise ImproperlyConfigured("Put 'django.core.context_processors.auth' in your TEMPLATE_CONTEXT_PROCESSORS setting in order to use the admin application.")
    268 
    269         # Delegate to the appropriate method, based on the URL.
    270         if url is None:
    271             return self.changelist_view(request)
    272         elif url.endswith('add'):
    273             return self.add_view(request)
    274         elif url.endswith('history'):
    275             return self.history_view(request, unquote(url[:-8]))
    276         elif url.endswith('delete'):
    277             return self.delete_view(request, unquote(url[:-7]))
    278         else:
    279             return self.change_view(request, unquote(url))
     278   
     279    def _get_urls(self):
     280        from django.conf.urls.defaults import patterns, url
     281        urls_module = types.ModuleType('%s.urls' % self.__class__.__name__)
     282        info = self.model._meta.app_label, self.model._meta.module_name
     283        urlpatterns = patterns('',
     284            url(r'^$', self.changelist_view, name='admin_%s_%s_changelist' % info),
     285            url(r'^add/$', self.add_view, name='admin_%s_%s_add' % info),
     286            url(r'^(.+)/history/$', self.history_view, name='admin_%s_%s_history' % info),
     287            url(r'^(.+)/delete/$', self.delete_view, name='admin_%s_%s_delete' % info),
     288            url(r'^(.+)/$', self.change_view, name='admin_%s_%s_change' % info),
     289        )
     290        urls_module.urlpatterns = urlpatterns
     291        return urls_module
     292    urls = property(_get_urls)
    280293
    281294    def _media(self):
    282295        from django.conf import settings
    class ModelAdmin(BaseModelAdmin): 
    480493            'content_type_id': ContentType.objects.get_for_model(model).id,
    481494            'save_as': self.save_as,
    482495            'save_on_top': self.save_on_top,
    483             'root_path': self.admin_site.root_path,
    484496        })
    485497        return render_to_response(self.change_form_template or [
    486498            "admin/%s/%s/change_form.html" % (app_label, opts.object_name.lower()),
    class ModelAdmin(BaseModelAdmin): 
    540552            'media': mark_safe(media),
    541553            'inline_admin_formsets': inline_admin_formsets,
    542554            'errors': AdminErrorList(form, inline_formsets),
    543             'root_path': self.admin_site.root_path,
    544555        }
    545556        context.update(extra_context or {})
    546557        return self.render_change_form(request, model, context, add=True)
     558    add_view = admin_perm_test(add_view)
    547559
    548560    def change_view(self, request, object_id, extra_context=None):
    549561        "The 'change' admin view for this model."
    class ModelAdmin(BaseModelAdmin): 
    618630            'media': mark_safe(media),
    619631            'inline_admin_formsets': inline_admin_formsets,
    620632            'errors': AdminErrorList(form, inline_formsets),
    621             'root_path': self.admin_site.root_path,
    622633        }
    623634        context.update(extra_context or {})
    624635        return self.render_change_form(request, model, context, change=True, obj=obj)
     636    change_view = admin_perm_test(change_view)
    625637
    626638    def changelist_view(self, request, extra_context=None):
    627639        "The 'change list' admin view for this model."
    class ModelAdmin(BaseModelAdmin): 
    648660            'is_popup': cl.is_popup,
    649661            'cl': cl,
    650662            'has_add_permission': self.has_add_permission(request),
    651             'root_path': self.admin_site.root_path,
    652663        }
    653664        context.update(extra_context or {})
    654665        return render_to_response(self.change_list_template or [
    class ModelAdmin(BaseModelAdmin): 
    656667            'admin/%s/change_list.html' % app_label,
    657668            'admin/change_list.html'
    658669        ], context, context_instance=template.RequestContext(request))
     670    changelist_view = admin_perm_test(changelist_view)
    659671
    660672    def delete_view(self, request, object_id, extra_context=None):
    661673        "The 'delete' admin view for this model."
    class ModelAdmin(BaseModelAdmin): 
    702714            "deleted_objects": deleted_objects,
    703715            "perms_lacking": perms_needed,
    704716            "opts": opts,
    705             "root_path": self.admin_site.root_path,
    706717        }
    707718        context.update(extra_context or {})
    708719        return render_to_response(self.delete_confirmation_template or [
    class ModelAdmin(BaseModelAdmin): 
    710721            "admin/%s/delete_confirmation.html" % app_label,
    711722            "admin/delete_confirmation.html"
    712723        ], context, context_instance=template.RequestContext(request))
     724    delete_view = admin_perm_test(delete_view)
    713725
    714726    def history_view(self, request, object_id, extra_context=None):
    715727        "The 'history' admin view for this model."
    class ModelAdmin(BaseModelAdmin): 
    728740            'action_list': action_list,
    729741            'module_name': capfirst(opts.verbose_name_plural),
    730742            'object': obj,
    731             'root_path': self.admin_site.root_path,
    732743        }
    733744        context.update(extra_context or {})
    734745        return render_to_response(self.object_history_template or [
    class ModelAdmin(BaseModelAdmin): 
    736747            "admin/%s/object_history.html" % opts.app_label,
    737748            "admin/object_history.html"
    738749        ], context, context_instance=template.RequestContext(request))
     750    history_view = admin_perm_test(history_view)
    739751
    740752class InlineModelAdmin(BaseModelAdmin):
    741753    """
  • django/contrib/admin/sites.py

    diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py
    index 6aa65c2..33f152e 100644
    a b import base64 
    1111import cPickle as pickle
    1212import datetime
    1313import md5
     14import types
    1415import re
    1516
    1617ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
    def _decode_post_data(encoded_data): 
    3940        raise SuspiciousOperation, "User may have tampered with session cookie."
    4041    return pickle.loads(pickled)
    4142
     43def admin_perm_test(func):
     44    def inner(admin_site, request, *args, **kwargs):
     45        if not admin_site.has_permission(request):
     46            response = admin_site.login(request)
     47            if response:         
     48                return response
     49        return func(admin_site, request, *args, **kwargs)
     50    return inner
     51
    4252class AdminSite(object):
    4353    """
    4454    An AdminSite object encapsulates an instance of the Django admin application, ready
    class AdminSite(object): 
    93103        *at least one* page in the admin site.
    94104        """
    95105        return request.user.is_authenticated() and request.user.is_staff
    96 
    97     def root(self, request, url):
    98         """
    99         Handles main URL routing for the admin app.
    100 
    101         `url` is the remainder of the URL -- e.g. 'comments/comment/'.
    102         """
    103         if request.method == 'GET' and not request.path.endswith('/'):
    104             return http.HttpResponseRedirect(request.path + '/')
    105        
    106         # Figure out the admin base URL path and stash it for later use
    107         self.root_path = re.sub(re.escape(url) + '$', '', request.path)
     106   
     107    def _get_urls(self):
     108        from django.conf.urls.defaults import patterns, url, include
     109        from django.core.urlresolvers import RegexURLResolver
    108110       
    109         url = url.rstrip('/') # Trim trailing slash, if it exists.
    110 
    111         # The 'logout' view doesn't require that the person is logged in.
    112         if url == 'logout':
    113             return self.logout(request)
    114 
    115         if not self.has_permission(request):
    116             response = self.login(request)
    117             if response:
    118                 # make sure that there is a response before returning
    119                 # this addresses any post data that might persist from
    120                 # expired sessions and continue through (#5999)
    121                 return response
    122 
    123         if url == '':
    124             return self.index(request)
    125         elif url == 'password_change':
    126             return self.password_change(request)
    127         elif url == 'password_change/done':
    128             return self.password_change_done(request)
    129         elif url == 'jsi18n':
    130             return self.i18n_javascript(request)
    131         # urls starting with 'r/' are for the "show in web" links
    132         elif url.startswith('r/'):
    133             from django.views.defaults import shortcut
    134             return shortcut(request, *url.split('/')[1:])
    135         else:
    136             match = USER_CHANGE_PASSWORD_URL_RE.match(url)
    137             if match:
    138                 return self.user_change_password(request, match.group(1))
    139                
    140             if '/' in url:
    141                 return self.model_page(request, *url.split('/', 2))
     111        urls_module = types.ModuleType('%s.urls' % self.__class__.__name__)
     112        urlpatterns = patterns('',
     113            url(r'^$', self.index, name='admin_index'),
     114            url(r'^logout/$', self.logout, name='admin_logout'),
     115            url(r'^password_change/$', self.password_change, name='admin_password_change'),
     116            url(r'^password_change_done/$', self.password_change_done, name='admin_password_change_done'),
     117            url(r'^jsi18n/$', self.i18n_javascript, name='admin_jsi18n'),
     118            url(r'^auth/user/(\d+)/password/$', self.user_change_password, name='admin_change_password'),
     119            url('^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', 'django.views.defaults.shortcut')
     120        )
    142121
    143         raise http.Http404('The requested admin page does not exist.')
     122        for model, model_admin in self._registry.iteritems():
     123            urlpatterns += patterns('',
     124                url('^%s/%s/' % (model._meta.app_label, model._meta.module_name), include(model_admin.urls))
     125            )
     126        urls_module.urlpatterns = urlpatterns
     127        return urls_module
     128    urls = property(_get_urls)
    144129
    145     def model_page(self, request, app_label, model_name, rest_of_url=None):
    146         """
    147         Handles the model-specific functionality of the admin site, delegating
    148         to the appropriate ModelAdmin class.
    149         """
    150         from django.db import models
    151         model = models.get_model(app_label, model_name)
    152         if model is None:
    153             raise http.Http404("App %r, model %r, not found." % (app_label, model_name))
    154         try:
    155             admin_obj = self._registry[model]
    156         except KeyError:
    157             raise http.Http404("This model exists but has not been registered with the admin site.")
    158         return admin_obj(request, rest_of_url)
    159     model_page = never_cache(model_page)
    160130
    161131    def password_change(self, request):
    162132        """
    class AdminSite(object): 
    164134        """
    165135        from django.contrib.auth.views import password_change
    166136        return password_change(request)
     137    passoword_change = admin_perm_test(password_change)
    167138
    168139    def password_change_done(self, request):
    169140        """
    class AdminSite(object): 
    171142        """
    172143        from django.contrib.auth.views import password_change_done
    173144        return password_change_done(request)
     145    password_change_done = admin_perm_test(password_change_done)
    174146
    175147    def user_change_password(self, request, id):
    176148        """
    class AdminSite(object): 
    178150        """
    179151        from django.contrib.auth.views import user_change_password
    180152        return user_change_password(request, id)
     153    user_change_password = admin_perm_test(user_change_password)
    181154
    182155    def i18n_javascript(self, request):
    183156        """
    class AdminSite(object): 
    192165        else:
    193166            from django.views.i18n import null_javascript_catalog as javascript_catalog
    194167        return javascript_catalog(request, packages='django.conf')
     168    i18n_javascript = admin_perm_test(i18n_javascript)
    195169
    196170    def logout(self, request):
    197171        """
    class AdminSite(object): 
    309283        context = {
    310284            'title': _('Site administration'),
    311285            'app_list': app_list,
    312             'root_path': self.root_path,
    313286        }
    314287        context.update(extra_context or {})
    315288        return render_to_response(self.index_template or 'admin/index.html', context,
    316289            context_instance=template.RequestContext(request)
    317290        )
    318     index = never_cache(index)
     291    index = never_cache(admin_perm_test(index))
    319292
    320293    def display_login_form(self, request, error_message='', extra_context=None):
    321294        request.session.set_test_cookie()
    class AdminSite(object): 
    333306            'app_path': request.path,
    334307            'post_data': post_data,
    335308            'error_message': error_message,
    336             'root_path': self.root_path,
    337309        }
    338310        context.update(extra_context or {})
    339311        return render_to_response(self.login_template or 'admin/login.html', context,
  • django/contrib/auth/admin.py

    diff --git a/django/contrib/auth/admin.py b/django/contrib/auth/admin.py
    index 998692a..e184353 100644
    a b class UserAdmin(admin.ModelAdmin): 
    5858            'opts': User._meta,
    5959            'save_as': False,
    6060            'username_help_text': User._meta.get_field('username').help_text,
    61             'root_path': self.admin_site.root_path,
    6261        }, context_instance=template.RequestContext(request))
    6362
    6463admin.site.register(Group, GroupAdmin)
  • django/core/urlresolvers.py

    diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
    index ff0bcbc..ba7908b 100644
    a b class RegexURLResolver(object): 
    204204        # urlconf_name is a string representing the module containing urlconfs.
    205205        self.regex = re.compile(regex, re.UNICODE)
    206206        self.urlconf_name = urlconf_name
     207        if not isinstance(self.urlconf_name, basestring):
     208            self._urlconf_module = self.urlconf_name
    207209        self.callback = None
    208210        self.default_kwargs = default_kwargs or {}
    209211        self._reverse_dict = {}
  • tests/regressiontests/admin_views/tests.py

    diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
    index 98ccab6..c79f868 100644
    a b class AdminViewPermissionsTest(TestCase): 
    8484            '/test_admin/admin/admin_views/article/add'
    8585        )
    8686        self.assertRedirects(request,
    87             '/test_admin/admin/admin_views/article/add/'
     87            '/test_admin/admin/admin_views/article/add/', status_code=301
    8888        )
    8989   
    9090    def testLogin(self):
    class AdminViewPermissionsTest(TestCase): 
    320320        self.assertRedirects(post, '/test_admin/admin/')
    321321        self.failUnlessEqual(Article.objects.all().count(), 0)
    322322        self.client.get('/test_admin/admin/logout/')
    323        
    324  No newline at end of file
     323       
  • tests/regressiontests/admin_views/urls.py

    diff --git a/tests/regressiontests/admin_views/urls.py b/tests/regressiontests/admin_views/urls.py
    index e556812..4fdfeb4 100644
    a b from django.contrib import admin 
    33
    44urlpatterns = patterns('',
    55    (r'^admin/doc/', include('django.contrib.admindocs.urls')),
    6     (r'^admin/(.*)', admin.site.root),
     6    (r'^admin/', include(admin.site.urls)),
    77)
Back to Top