Changes between Version 14 and Version 15 of NewformsAdminBranch


Ignore:
Timestamp:
Apr 7, 2007, 12:07:12 AM (18 years ago)
Author:
Adrian Holovaty
Comment:

Added a whole bunch of documentation/status

Legend:

Unmodified
Added
Removed
Modified
  • NewformsAdminBranch

    v14 v15  
    1515In no particular order, here are the goals of this branch. This list may expand as we get more ideas.
    1616
    17   * Core goals
    18     * Change the admin site to use newforms instead of automatic manipulators.
    19     * Enable developers to declare custom widgets for particular fields in a model.
    20     * Enable developers to declare custom admin-only validation for a model (i.e., validation logic that is applied only in the admin site, nowhere else).
    21     * Give developers extra hooks into the admin-site functionality. (Yes, this is a broad goal. More examples are forthcoming.)
    22     * Integrate some ideas from #2248: Remove {{{core=True}}}, specify inline models in the model itself rather than in the related model, specify which fields should be displayed inline.
     17  * Change the admin site to use newforms instead of automatic manipulators.
     18  * Enable developers to declare custom widgets for particular fields in a model.
     19  * Enable developers to declare custom admin-only validation for a model (i.e., validation logic that is applied only in the admin site, nowhere else).
     20  * Give developers extra hooks into the admin-site functionality. (Yes, this is a broad goal. More examples are forthcoming.)
     21  * Remove the admin declarations ({{{class Admin}}}) from within models, thereby helping decouple the admin system from models.
     22  * Integrate some ideas from #2248: Remove {{{core=True}}}, specify inline models in the model itself rather than in the related model, specify which fields should be displayed inline.
    2323
    24 The [http://code.djangoproject.com/browser/django/trunk/django/contrib/formtools/preview.py django.contrib.formtools.preview.FormPreview application] (not yet documented, but fully implemented) elegantly allows for fine-grained customization of the application by subclassing. A similar approach would be a great fit for the Django admin site: Write a class that subclasses a base class called {{{ModelAdmin}}} and specify whichever customizations you need to make -- from the current basic admin options such as {{{list_display}}} and {{{search_fields}}} to full-on Python hooks, such as defining arbitrary Python code to run before or after a model object is saved via the admin.
     24The [http://code.djangoproject.com/browser/django/trunk/django/contrib/formtools/preview.py django.contrib.formtools.preview.FormPreview application] (not yet documented, but fully implemented) elegantly allows for fine-grained customization of the application by subclassing. We're taking a similar approach for the new version of the Django admin site: Write a class that subclasses a base class called {{{ModelAdmin}}} and specify whichever customizations you need to make -- from the current basic admin options such as {{{list_display}}} and {{{search_fields}}} to full-on Python hooks, such as defining arbitrary Python code to run before or after a model object is saved via the admin.
    2525
    26 We should keep in mind this future goal as we implement the newforms-admin branch. Although we don't have to implement all of this hooks for the time being, we should ensure this branch's changes are future-compatible with these plans.
     26== Status ==
    2727
    28 == Roadmap ==
     28A lot has changed in this branch. Let's start the syntax for URLconfs:
    2929
    30 || Change admin URLconf so that the five model-specific views ({{{change_list}}}, {{{add_stage}}}, {{{history}}}, {{{delete_stage}}}, {{{change_stage}}}) point to the {{{class Admin}}} in the appropriate model, rather than pointing at the {{{django.contrib.admin}}} view functions. || Done in [4315] ||
    31 || Create a class {{{django.contrib.admin.options.ModelAdmin}}}, which implements the admin hooks for a particular model. || Done in [4315] ||
    32 || Implement {{{has_add_permission()}}}, {{{has_change_permission()}}} and {{{has_delete_permission()}}} hooks on {{{ModelAdmin}}}, so people can implement specific permission logic (such as per-object permissions). || Done in [4324] ||
    33 || Change model infastructure/metaclass so that the inner {{{class Admin}}} automatically subclasses {{{ModelAdmin}}}. (This is a bit of black magic, but it's necessary for backwards compatibility. We may require an explicit subclass declaration in the future.) || Done in [4328] ||
    34 || Implement {{{ModelAdmin.add_view}}} as a method rather than the {{{add_stage}}} view function. || Done in [4323]. ||
    35 || Implement {{{ModelAdmin.change_view}}} as a method rather than the {{{change_stage}}} view function. || Done in [4322]. ||
    36 || Implement {{{ModelAdmin.change_list_view}}}. || Done in [4320] ||
    37 || Implement {{{ModelAdmin.history_view}}}. || Done in [4319] ||
    38 || Implement {{{ModelAdmin.delete_view}}}. || Done in [4321] ||
    39 || Change {{{_meta.admin}}} on a model to be a {{{ModelAdmin}}} class instead of a {{{AdminOptions}}} instance, and remove the {{{AdminOptions}}} class. || Done in [4343] ||
    40 || Clean up some of the admin: fold {{{ChangeList}}} methods/functionality into {{{ModelAdmin}}}. || Not done yet ||
    41 || Change {{{ModelAdmin.add_view}}} to use newforms. || Done ||
    42 || Change {{{ModelAdmin.change_view}}} to use newforms. || Done ||
    43 || Change {{{raw_id_admin}}} so that it's a {{{class Admin}}} option rather than being a database {{{Field}}} option. || Done in [4430] ||
    44 || Figure out a cleaner way of specifying admin options, now that {{{class Admin}}} is much more powerful. It doesn't feel like it should live in the model anymore. || Done; see [http://groups.google.com/group/django-developers/browse_frm/thread/d94c7b11392c5085/ discussion] ||
    45 || Implement edit-inline functionality || Not done yet ||
     30{{{
     31#!python
     32
     33# OLD:
     34from django.conf.urls.defaults import *
     35
     36urlpatterns = patterns('',
     37    (r'^admin/', include('django.contrib.admin.urls')),
     38)
     39
     40# NEW:
     41from django.conf.urls.defaults import *
     42from django.contrib import admin
     43
     44urlpatterns = patterns('',
     45    ('^admin/(.*)', admin.site.root),
     46)
     47}}}
     48
     49Note that, in this above URLconf example, we're dealing with the object {{{django.contrib.admin.site}}}. This is an instance of {{{django.contrib.admin.AdminSite}}}, which is a class that lets you specify admin-site functionality. The object {{{django.contrib.admin.site}}} is a default {{{AdminSite}}} instance that is created for you automatically, but you can also create other instances as you see fit. Previously, there was one "global" version of the admin site, which used all models that contained a {{{class Admin}}}. This new scheme allows for much more fine-grained control over your admin sites, allowing you to have multiple admin sites in the same Django instance.
     50
     51In this example, we create two {{{AdminSite}}} instances, registering different models with both. Assume {{{Book}}}, {{{Author}}}, {{{Musician}}} and {{{Instrument}}} are Django model classes (not instances).
     52
     53{{{
     54#!python
     55from django.contrib import admin
     56
     57site1 = admin.AdminSite()
     58site1.register(Book)
     59site1.register(Author)
     60
     61site2 = admin.AdminSite()
     62site2.register(Musician)
     63site2.register(Instrument)
     64
     65# URLconf
     66
     67from django.conf.urls.defaults import *
     68
     69urlpatterns = patterns('',
     70    ('^book_admin/(.*)', site1),
     71    ('^music_admin/(.*)', site2),
     72)
     73}}}
     74
     75With this example, if you go to {{{/book_admin/}}}, you'll get a Django admin site for the {{{Book}}} and {{{Author}}} models. If you go to {{{/music_admin/}}}, you'll get a Django admin site for the {{{Musician}}} and {{{Instrument}}} models.
     76
     77Admin options -- the inner {{{class Admin}}} -- have changed, too. Models no longer use an inner class to declare their admin site options. In fact, *all admin functionality has been decoupled from the model syntax*! How, then, do we declare admin options? Like this:
     78
     79{{{
     80#!python
     81# a sample models.py file
     82from django.db import models
     83
     84class Author(models.Model):
     85    first_name = models.CharField(maxlength=30)
     86    last_name = models.CharField(maxlength=30)
     87
     88    def __str__(self):
     89        return '%s %s' % (self.first_name, self.last_name)
     90
     91class Book(models.Model):
     92    title = models.CharField(maxlength=100)
     93    author = models.ForeignKey(Author)
     94
     95from django.contrib import admin
     96
     97class BookOptions(admin.ModelAdmin):
     98    list_display = ('title', 'author')
     99    ordering = ('title',)
     100
     101admin.site.register(Author)
     102admin.site.register(Book, BookOptions)
     103}}}
     104
     105In this example, we register both {{{Author}}} and {{{Book}}} with the {{{AdminSite}}} instance {{{django.contrib.admin.site}}}. {{{Author}}} doesn't need any custom admin options, so we just call {{{admin.site.register(Author)}}}. {{{Book}}}, on the other hand, has some custom admin options, so we define a {{{BookOptions}}} class and pass that class as a second argument to {{{admin.site.register()}}}.
     106
     107You'll notice the {{{BookOptions}}} class looks a lot like the old-style {{{class Admin}}}. Almost all of the old {{{class Admin}}} options work exactly the same, with one or two exceptions. (For the options that have changed, we've made them *much* more powerful.) In addition to the classic options such as {{{list_display}}} and {{{ordering}}}, the {{{ModelAdmin}}} class introduces a wealth of extra hooks you can use to customize the admin site for that particular model. For example:
     108
     109{{{
     110#!python
     111
     112class BookOptions(admin.ModelAdmin):
     113    list_display = ('title', 'author')
     114    ordering = ('title',)
     115
     116    def has_change_permission(self, request, obj):
     117        """
     118        John can only edit books by Roald Dahl.
     119        """
     120        if request.user.username == 'john':
     121            return obj.author.id = 3 # Roald Dahl books
     122        return super(BookOptions, self).has_change_permission(request, obj)
     123}}}
     124
     125Look at the class {{{ModelAdmin}}} in the file django/contrib/admin/options.py to see all of the methods you can override. This is exciting stuff.
     126
     127== To-do list ==
     128
     129(Updated April 6, 2007)
     130
     131  * Implement "edit inline" functionality.
    46132
    47133== Backwards-incompatible changes ==
Back to Top