= The newforms-admin branch = This branch aims to integrate Django's admin site with the [http://www.djangoproject.com/documentation/newforms/ newforms library]. Along the way, we'll take the opportunity to add extra customization hooks to the admin site, in preparation for a complete admin-site refactoring in the future. == How to get the branch == {{{ svn co http://code.djangoproject.com/svn/django/branches/newforms-admin/ }}} See our [http://www.djangoproject.com/documentation/contributing/#branch-policy branch policy] for full information on how to use a branch. == Goals == In no particular order, here are the goals of this branch. This list may expand as we get more ideas. * Core goals * Change the admin site to use newforms instead of automatic manipulators. * Enable developers to declare custom widgets for particular fields in a model. * 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). * Give developers extra hooks into the admin-site functionality. (Yes, this is a broad goal. More examples are forthcoming.) * 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. 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. 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. == Roadmap == || 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] || || Create a class {{{django.contrib.admin.options.ModelAdmin}}}, which implements the admin hooks for a particular model. || Done in [4315] || || 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] || || 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] || || Implement {{{ModelAdmin.add_view}}} as a method rather than the {{{add_stage}}} view function. || Done in [4323]. || || Implement {{{ModelAdmin.change_view}}} as a method rather than the {{{change_stage}}} view function. || Done in [4322]. || || Implement {{{ModelAdmin.change_list_view}}}. || Done in [4320] || || Implement {{{ModelAdmin.history_view}}}. || Done in [4319] || || Implement {{{ModelAdmin.delete_view}}}. || Done in [4321] || || Change {{{_meta.admin}}} on a model to be a {{{ModelAdmin}}} class instead of a {{{AdminOptions}}} instance, and remove the {{{AdminOptions}}} class. || Done in [4343] || || Clean up some of the admin: fold {{{ChangeList}}} methods/functionality into {{{ModelAdmin}}}. || Not done yet || || Change {{{ModelAdmin.add_view}}} to use newforms. || Done || || Change {{{ModelAdmin.change_view}}} to use newforms. || Done || || Change {{{raw_id_admin}}} so that it's a {{{class Admin}}} option rather than being a database {{{Field}}} option. || Done in [4430] || || 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] || || Implement edit-inline functionality || Not done yet || == Backwards-incompatible changes == This is a (currently incomplete) list of backwards-incompatible changes made in this branch. === Changed Admin.manager option to more flexible hook === As of [4342], the {{{manager}}} option to {{{class Admin}}} no longer exists. This option was undocumented, but we're mentioning the change here in case you used it. In favor of this option, {{{class Admin}}} may now define one of these methods: * {{{queryset()}}} * {{{queryset_add()}}} * {{{queryset_change()}}} These give you much more flexibility. Note that this change was made to the NewformsAdminBranch. (We initially called the new method {{{change_list_queryset}}}, but this was changed in [4584] to be more flexible.) The change will not be made to trunk until that branch is merged to trunk. === Changed prepopulate_from to be defined in the Admin class, not database field classes === As of [4446], the {{{prepopulate_from}}} option to database fields no longer exists. It's been discontinued in favor of the new {{{prepopulated_fields}}} option on {{{class Admin}}}. The new {{{prepopulated_fields}}} option, if given, should be a dictionary mapping field names to lists/tuples of field names. Here's an example comparing old syntax and new syntax: {{{ #!python # OLD: class MyModel(models.Model): first_name = models.CharField(maxlength=30) last_name = models.CharField(maxlength=30) slug = models.CharField(maxlength=60, prepopulate_from=('first_name', 'last_name')) class Admin: pass # NEW: class MyModel(models.Model): first_name = models.CharField(maxlength=30) last_name = models.CharField(maxlength=30) slug = models.CharField(maxlength=60) class Admin: prepopulated_fields = {'slug': ('first_name', 'last_name')} }}} Note that this change was made to the NewformsAdminBranch. The change will not be made to trunk until that branch is merged to trunk. === Moved admin doc views into django.contrib.admindocs === As of [4585], the documentation views for the Django admin site were moved into a new package, {{{django.contrib.admindocs}}}. The admin docs, which aren't documented very well, were located at {{{docs/}}} in the admin site. They're also linked-to by the "Documentation" link in the upper right of default admin templates. Because we've moved the doc views, you now have to activate admin docs explicitly. Do this by adding the following line to your URLconf: {{{ #!python (r'^admin/doc/', include('django.contrib.admindocs.urls')), }}} Note that this change was made to the NewformsAdminBranch. The change will not be made to trunk until that branch is merged to trunk.