Django

Code

Changeset 7630

Show
Ignore:
Timestamp:
06/13/08 10:42:43 (4 months ago)
Author:
simon
Message:

newforms-admin: Made it easier to specify a custom template to be used in the admin section. You can now specify index_template and login_template properties on an AdminSite? subclass, and change_form_template, change_list_template, object_history_template and delete_confirmation_template properties on a ModelAdmin? subclass.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/newforms-admin/django/contrib/admin/options.py

    r7627 r7630  
    6060    def __init__(self, form, fieldsets, prepopulated_fields): 
    6161        self.form, self.fieldsets = form, fieldsets 
    62         self.prepopulated_fields = [{'field': form[field_name], 'dependencies': [form[f] for f in dependencies]} for field_name, dependencies in prepopulated_fields.items()] 
     62        self.prepopulated_fields = [{ 
     63            'field': form[field_name], 
     64            'dependencies': [form[f] for f in dependencies] 
     65        } for field_name, dependencies in prepopulated_fields.items()] 
    6366 
    6467    def __iter__(self): 
     
    234237    ordering = None 
    235238    inlines = [] 
     239     
     240    # Custom templates (designed to be over-ridden in subclasses) 
     241    change_form_template = None 
     242    change_list_template = None 
     243    delete_confirmation_template = None 
     244    object_history_template = None 
    236245 
    237246    def __init__(self, model, admin_site): 
     
    373382                post_url_continue += "?_popup=1" 
    374383            return HttpResponseRedirect(post_url_continue % pk_value) 
     384         
    375385        if request.POST.has_key("_popup"): 
    376386            return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \ 
     
    471481            'save_on_top': self.save_on_top, 
    472482        }) 
    473         return render_to_response(
     483        return render_to_response(self.change_form_template or
    474484            "admin/%s/%s/change_form.html" % (app_label, opts.object_name.lower()), 
    475485            "admin/%s/change_form.html" % app_label, 
     
    627637                return render_to_response('admin/invalid_setup.html', {'title': _('Database error')}) 
    628638            return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1') 
     639         
    629640        context = { 
    630641            'title': cl.title, 
     
    634645        context.update({'has_add_permission': self.has_add_permission(request)}), 
    635646        context.update(extra_context or {}) 
    636         return render_to_response(
     647        return render_to_response(self.change_list_template or
    637648            'admin/%s/%s/change_list.html' % (app_label, opts.object_name.lower()), 
    638649            'admin/%s/change_list.html' % app_label, 
     
    677688                return HttpResponseRedirect("../../../../") 
    678689            return HttpResponseRedirect("../../") 
     690         
    679691        context = { 
    680692            "title": _("Are you sure?"), 
     
    686698        } 
    687699        context.update(extra_context or {}) 
    688         return render_to_response(
     700        return render_to_response(self.delete_confirmation_template or
    689701            "admin/%s/%s/delete_confirmation.html" % (app_label, opts.object_name.lower()), 
    690702            "admin/%s/delete_confirmation.html" % app_label, 
     
    698710        model = self.model 
    699711        opts = model._meta 
    700         action_list = LogEntry.objects.filter(object_id=object_id, 
    701             content_type__id__exact=ContentType.objects.get_for_model(model).id).select_related().order_by('action_time') 
     712        action_list = LogEntry.objects.filter( 
     713            object_id = object_id, 
     714            content_type__id__exact = ContentType.objects.get_for_model(model).id 
     715        ).select_related().order_by('action_time') 
    702716        # If no history was found, see whether this object even exists. 
    703717        obj = get_object_or_404(model, pk=object_id) 
     
    709723        } 
    710724        context.update(extra_context or {}) 
    711         return render_to_response(
     725        return render_to_response(self.object_history_template or
    712726            "admin/%s/%s/object_history.html" % (opts.app_label, opts.object_name.lower()), 
    713727            "admin/%s/object_history.html" % opts.app_label, 
  • django/branches/newforms-admin/django/contrib/admin/sites.py

    r7611 r7630  
    2424    pass 
    2525 
    26 def _display_login_form(request, error_message=''): 
    27     request.session.set_test_cookie() 
    28     if request.POST and request.POST.has_key('post_data'): 
    29         # User has failed login BUT has previously saved post data. 
    30         post_data = request.POST['post_data'] 
    31     elif request.POST: 
    32         # User's session must have expired; save their post data. 
    33         post_data = _encode_post_data(request.POST) 
    34     else: 
    35         post_data = _encode_post_data({}) 
    36     return render_to_response('admin/login.html', { 
    37         'title': _('Log in'), 
    38         'app_path': request.path, 
    39         'post_data': post_data, 
    40         'error_message': error_message 
    41     }, context_instance=template.RequestContext(request)) 
    42  
    4326def _encode_post_data(post_data): 
    4427    from django.conf import settings 
     
    5740 
    5841class AdminSite(object): 
     42    """ 
     43    An AdminSite object encapsulates an instance of the Django admin application, ready 
     44    to be hooked in to your URLConf. Models are registered with the AdminSite using the 
     45    register() method, and the root() method can then be used as a Django view function 
     46    that presents a full admin interface for the collection of registered models. 
     47    """ 
     48     
     49    index_template = None 
     50    login_template = None 
     51     
    5952    def __init__(self): 
    6053        self._registry = {} # model_class class -> admin_class instance 
     
    120113                # expired sessions and continue through (#5999) 
    121114                return response 
    122  
    123115 
    124116        if url == '': 
     
    215207            else: 
    216208                message = "" 
    217             return _display_login_form(request, message) 
     209            return self.display_login_form(request, message) 
    218210 
    219211        # Check that the user accepts cookies. 
    220212        if not request.session.test_cookie_worked(): 
    221213            message = _("Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again.") 
    222             return _display_login_form(request, message) 
     214            return self.display_login_form(request, message) 
    223215 
    224216        # Check the password. 
     
    236228                else: 
    237229                    message = _("Your e-mail address is not your username. Try '%s' instead.") % user.username 
    238             return _display_login_form(request, message) 
     230            return self.display_login_form(request, message) 
    239231 
    240232        # The user data is correct; log in the user in and continue. 
     
    256248                        return http.HttpResponseRedirect(request.path) 
    257249            else: 
    258                 return _display_login_form(request, ERROR_MESSAGE) 
     250                return self.display_login_form(request, ERROR_MESSAGE) 
    259251 
    260252    def index(self, request): 
     
    301293            app['models'].sort(lambda x, y: cmp(x['name'], y['name'])) 
    302294 
    303         return render_to_response('admin/index.html', { 
     295        return render_to_response(self.index_template or 'admin/index.html', { 
    304296            'title': _('Site administration'), 
    305297            'app_list': app_list, 
    306298        }, context_instance=template.RequestContext(request)) 
    307299 
     300    def display_login_form(self, request, error_message=''): 
     301        request.session.set_test_cookie() 
     302        if request.POST and request.POST.has_key('post_data'): 
     303            # User has failed login BUT has previously saved post data. 
     304            post_data = request.POST['post_data'] 
     305        elif request.POST: 
     306            # User's session must have expired; save their post data. 
     307            post_data = _encode_post_data(request.POST) 
     308        else: 
     309            post_data = _encode_post_data({}) 
     310        return render_to_response(self.login_template or 'admin/login.html', { 
     311            'title': _('Log in'), 
     312            'app_path': request.path, 
     313            'post_data': post_data, 
     314            'error_message': error_message 
     315        }, context_instance=template.RequestContext(request)) 
     316 
     317 
    308318# This global object represents the default admin site, for the common case. 
    309319# You can instantiate AdminSite in your own code to create a custom admin site. 
  • django/branches/newforms-admin/tests/regressiontests/admin_views/models.py

    r7628 r7630  
    11from django.db import models 
    22from django.contrib import admin 
    3  
    43 
    54class Article(models.Model): 
     
    2524 
    2625class CustomArticleAdmin(admin.ModelAdmin): 
     26    """ 
     27    Tests various hooks for using custom templates and contexts. 
     28    """ 
     29    change_list_template = 'custom_admin/change_list.html' 
     30    change_form_template = 'custom_admin/change_form.html' 
     31    object_history_template = 'custom_admin/object_history.html' 
     32    delete_confirmation_template = 'custom_admin/delete_confirmation.html' 
     33     
    2734    def changelist_view(self, request): 
    2835        "Test that extra_context works" 
  • django/branches/newforms-admin/tests/regressiontests/admin_views/tests.py

    r7627 r7630  
    66 
    77# local test models 
    8 from models import Article 
     8from models import Article, CustomArticle 
    99 
    1010def get_perm(Model, perm): 
     
    184184        self.client.get('/test_admin/admin/logout/') 
    185185         
    186     def testCustomChangelistView(self): 
     186    def testCustomModelAdminTemplates(self): 
    187187        self.client.get('/test_admin/admin/') 
    188188        self.client.post('/test_admin/admin/', self.super_login) 
     189         
     190        # Test custom change list template with custom extra context 
    189191        request = self.client.get('/test_admin/admin/admin_views/customarticle/') 
    190192        self.failUnlessEqual(request.status_code, 200) 
    191193        self.assert_("var hello = 'Hello!';" in request.content) 
    192  
     194        self.assertTemplateUsed(request, 'custom_admin/change_list.html') 
     195         
     196        # Test custom change form template 
     197        request = self.client.get('/test_admin/admin/admin_views/customarticle/add/') 
     198        self.assertTemplateUsed(request, 'custom_admin/change_form.html') 
     199         
     200        # Add an article so we can test delete and history views 
     201        post = self.client.post('/test_admin/admin/admin_views/customarticle/add/', { 
     202            'content': '<p>great article</p>', 
     203            'date_0': '2008-03-18', 
     204            'date_1': '10:54:39' 
     205        }) 
     206        self.assertRedirects(post, '/test_admin/admin/admin_views/customarticle/') 
     207        self.failUnlessEqual(CustomArticle.objects.all().count(), 1) 
     208         
     209        # Test custom delete and object history templates 
     210        request = self.client.get('/test_admin/admin/admin_views/customarticle/1/delete/') 
     211        self.assertTemplateUsed(request, 'custom_admin/delete_confirmation.html') 
     212        request = self.client.get('/test_admin/admin/admin_views/customarticle/1/history/') 
     213        self.assertTemplateUsed(request, 'custom_admin/object_history.html') 
     214         
     215        self.client.get('/test_admin/admin/logout/') 
     216         
     217    def testCustomAdminSiteTemplates(self): 
     218        from django.contrib import admin 
     219        self.assertEqual(admin.site.index_template, None) 
     220        self.assertEqual(admin.site.login_template, None) 
     221         
     222        self.client.get('/test_admin/admin/logout/') 
     223        request = self.client.get('/test_admin/admin/') 
     224        self.assertTemplateUsed(request, 'admin/login.html') 
     225        self.client.post('/test_admin/admin/', self.changeuser_login) 
     226        request = self.client.get('/test_admin/admin/') 
     227        self.assertTemplateUsed(request, 'admin/index.html') 
     228         
     229        self.client.get('/test_admin/admin/logout/') 
     230        admin.site.login_template = 'custom_admin/login.html' 
     231        admin.site.index_template = 'custom_admin/index.html' 
     232        request = self.client.get('/test_admin/admin/') 
     233        self.assertTemplateUsed(request, 'custom_admin/login.html') 
     234        self.assert_('Hello from a custom login template' in request.content) 
     235        self.client.post('/test_admin/admin/', self.changeuser_login) 
     236        request = self.client.get('/test_admin/admin/') 
     237        self.assertTemplateUsed(request, 'custom_admin/index.html') 
     238        self.assert_('Hello from a custom index template' in request.content) 
     239         
     240        self.client.get('/test_admin/admin/logout/') 
     241        admin.site.login_template = None 
     242        admin.site.index_template = None 
     243     
    193244    def testDeleteView(self): 
    194245        """Delete view should restrict access and actually delete items."""