| 42 | | class AdminSite(object): |
| | 42 | class instance_decorator(object): |
| | 43 | ''' |
| | 44 | Applies one or more decorators to the given instance method. |
| | 45 | |
| | 46 | Normal decorators do not work well within class definitions, |
| | 47 | because the decorated function will be passed the `self` |
| | 48 | parameter. This descriptor avoids that problem by decorating the |
| | 49 | function after it has been bound as an instance method. |
| | 50 | ''' |
| | 51 | def __init__(self, *decorators): |
| | 52 | self._decorators = decorators |
| | 53 | |
| | 54 | def __get__(self, instance, owner): |
| | 55 | f = new.instancemethod(self.f, instance, owner) |
| | 56 | for dec in self._decorators: |
| | 57 | f = dec(f) |
| | 58 | return f |
| | 59 | |
| | 60 | def __call__(self, f): |
| | 61 | self.f = f |
| | 62 | return self |
| | 63 | |
| | 64 | |
| | 65 | def _has_permission(request): |
| 90 | | def has_permission(self, request): |
| 91 | | """ |
| 92 | | Returns True if the given HttpRequest has permission to view |
| 93 | | *at least one* page in the admin site. |
| 94 | | """ |
| 95 | | return request.user.is_authenticated() and request.user.is_staff |
| | 122 | def get_url_patterns(self): |
| | 123 | # FIXME: I don't know how to handle the "show in web" links |
| | 124 | return [ |
| | 125 | url(r'^logout/$', self.logout), |
| | 126 | url(r'^$', self.index), |
| | 127 | url(r'^password_change/$', self.password_change), |
| | 128 | url(r'^password_change/done/$', self.password_change_done), |
| | 129 | url(r'jsi18n/$', self.i18n_javascript) |
| | 130 | ] |
| 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 | | # Figure out the admin base URL path and stash it for later use |
| 104 | | self.root_path = re.sub(re.escape(url) + '$', '', request.path) |
| 105 | | |
| 106 | | url = url.rstrip('/') # Trim trailing slash, if it exists. |
| 107 | | |
| 108 | | # The 'logout' view doesn't require that the person is logged in. |
| 109 | | if url == 'logout': |
| 110 | | return self.logout(request) |
| 111 | | |
| 112 | | if not self.has_permission(request): |
| 113 | | response = self.login(request) |
| 114 | | if response: |
| 115 | | # make sure that there is a response before returning |
| 116 | | # this addresses any post data that might persist from |
| 117 | | # expired sessions and continue through (#5999) |
| 118 | | return response |
| 119 | | |
| 120 | | if url == '': |
| 121 | | return self.index(request) |
| 122 | | elif url == 'password_change': |
| 123 | | return self.password_change(request) |
| 124 | | elif url == 'password_change/done': |
| 125 | | return self.password_change_done(request) |
| 126 | | elif url == 'jsi18n': |
| 127 | | return self.i18n_javascript(request) |
| 128 | | # urls starting with 'r/' are for the "show in web" links |
| 129 | | elif url.startswith('r/'): |
| 130 | | from django.views.defaults import shortcut |
| 131 | | return shortcut(request, *url.split('/')[1:]) |
| 132 | | else: |
| 133 | | match = USER_CHANGE_PASSWORD_URL_RE.match(url) |
| 134 | | if match: |
| 135 | | return self.user_change_password(request, match.group(1)) |
| 136 | | |
| 137 | | if '/' in url: |
| 138 | | return self.model_page(request, *url.split('/', 2)) |
| 139 | | |
| 140 | | raise http.Http404('The requested admin page does not exist.') |
| 141 | | |