diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py index 522032ec8d..b236dc8f93 100644 --- a/django/contrib/admin/sites.py +++ b/django/contrib/admin/sites.py @@ -53,12 +53,14 @@ def _decode_post_data(encoded_data): class AdminSite(object): def __init__(self): - self._registry = {} # model_class -> admin_class + self._registry = {} # model_class class -> admin_class instance def register(self, model_or_iterable, admin_class=None, **options): """ Registers the given model(s) with the given admin class. + The model(s) should be Model classes, not instances. + If an admin class isn't given, it will use ModelAdmin (the default admin options). If keyword arguments are given -- e.g., list_display -- they'll be applied as options to the admin class. @@ -72,7 +74,7 @@ class AdminSite(object): for model in model_or_iterable: if model in self._registry: raise AlreadyRegistered('The model %s is already registered' % model.__class__.__name__) - self._registry[model] = admin_class + self._registry[model] = admin_class(model) def unregister(self, model_or_iterable): """ @@ -100,25 +102,80 @@ class AdminSite(object): `url` is the remainder of the URL -- e.g. 'comments/comment/'. """ + url = url.rstrip('/') # Trim trailing slash, if it exists. + + # The 'logout' view doesn't require that the person is logged in. + if url == 'logout': + return self.logout(request) + if not self.has_permission(request): return self.login(request) - url = url.rstrip('/') # Trim trailing slash, if it exists. + if url == '': return self.index(request) elif url == 'password_change': return self.password_change(request) elif url == 'password_change/done': return self.password_change_done(request) - raise NotImplementedError('Only the admin index page is implemented.') + elif url == 'jsi18n': + return self.i18n_javascript(request) + elif '/' in url: + return self.model_page(request, *url.split('/', 2)) + + raise http.Http404('The requested admin page does not exist.') + + def model_page(self, request, app_label, model_name, rest_of_url=None): + """ + Handles the model-specific functionality of the admin site, delegating + to the appropriate ModelAdmin class. + """ + from django.db import models + model = models.get_model(app_label, model_name) + if model is None: + raise http.Http404("App %r, model %r, not found." % (app_label, model_name)) + try: + admin_obj = self._registry[model] + except KeyError: + raise http.Http404("This model exists but has not been registered with the admin site.") + return admin_obj(request, rest_of_url) def password_change(self, request): + """ + Handles the "change password" task -- both form display and validation. + """ from django.contrib.auth.views import password_change return password_change(request) def password_change_done(self, request): + """ + Displays the "success" page after a password change. + """ from django.contrib.auth.views import password_change_done return password_change_done(request) + def i18n_javascript(self, request): + """ + Displays the i18n JavaScript that the Django admin requires. + + This takes into account the USE_I18N setting. If it's set to False, the + generated JavaScript will be leaner and faster. + """ + from django.conf import settings + if settings.USE_I18N: + from django.views.i18n import javascript_catalog + else: + from django.views.i18n import null_javascript_catalog as javascript_catalog + return javascript_catalog(request, packages='django.conf') + + def logout(self, request): + """ + Logs out the user for the given HttpRequest. + + This should *not* assume the user is already logged in. + """ + from django.contrib.auth.views import logout + return logout(request) + def login(self, request): """ Displays the login form for the given HttpRequest. @@ -173,6 +230,10 @@ class AdminSite(object): return _display_login_form(request, ERROR_MESSAGE) def index(self, request): + """ + Displays the main admin index page, which lists all of the installed + apps that have been registered in this site. + """ app_list = [] user = request.user for model, model_admin in self._registry.items():