We (GCap, large commercial radio company in the UK) have been developing against the newforms-admin branch for a few months now, and based on that experience I have a number of suggestions for simple hooks that could be added to make it easier to customise.
1. Provide a custom template for a changelist / change form You should be able to specify a custom template for those pages in some way on the ModelAdmin object. At the moment select_template() is used to allow custom templates to be specified, but that isn't nearly flexible enough: it forces you to name your templates according to a certain naming scheme (e.g. admin/events/venue/change_form.html) but that means that you can't offer two admin interfaces with different templates for editing a specific thing, which is kind of the whole point of newforms admin allowing you to set up more than one admin site. It also forces you to keep your templates in an admin/ hierarchy which can be a bit limiting. There are two potential solutions to this. The first is to have a change_form_template option on the ModelAdmin: class EventAdmin(ModelAdmin): change_form_template = 'foo/bar/event_change_form.html' The other is to have the template provided by a method which can be over-ridden: class EventAdmin(ModelAdmin): def change_form_template(self, object=None): return select_template(['foo.html', 'bar.html']) Either look OK to me - the second is probably better as it lets you run a bit of logic to decide which template to use. Another benefit of this approach: it makes it easier to extend the default admin template without fear of running in to the dreaded template recursion problem. Custom templates for ModelAdmins is absolutely my number one request for newforms admin. It would make a huge number of customisations a great deal easier (we have a UED guy who keeps on coming up with genuinely good ideas for tweaks to our various admin screens). 2. Better hooks for custom form fields (esp. ForeignKey choices) Every time I write a formfield_for_dbfield method I want to strangle a kitten. I am not alone; this is pretty much the consensus among the developers I work with. There really, really needs to be a better way of doing per-form-field customisations. One extremely important example is being able to alter the choices in a ForeignKey or ManyToMany field, as discussed on this ticket: http://code.djangoproject.com/ticket/3987 This is critically important because one of the big new features in newforms-admin is the ability to do row-level permissions, thanks to the extremely neat has_change_permission / has_change_permission / has_delete_permission hooks and the ability to over-ride the queryset for a changelist. Unfortunately this doesn't go quite far enough. If you're dealing with row level permissions ("user X can edit article Y") you also need to be able to restrict foreign key relationships. User X might only be allowed to assign an article to 4 out of the 30 categories on a site, for example. Ticket #3987 solves this in a reasonable way, but I'm not too keen on the suggested dynamic method name (dynamic_FIELDNAME_choices). I talked this over a bit with Stuart Langridge and we came up with the following: class BookAdmin(ModelAdmin): ... def choices_for_author(self, request, book=None): user = request.user if not book: # Creating a new book: return queryset for author choices that # the current user is allowed to assign else: # Editing an existing book; maybe do something a bit different? Using choices_for_FIELDNAME feels like it fits better with existing Django conventions (like clean_FIELDNAME in newforms). Then we thought, why not take this further? The most common things you do with formfield_for_dbfield are setting a custom widget and setting a custom formfield. So why not allow these: def widget_for_author(...): return CustomWidgetOfSomeSort() def formfield_for_title(...): return FormFieldOfSomeSort() But what if you want to reuse the same method for many different fields? We could provide fallback methods widget_for(self, dbfield), formfield_for(self, dbfield) and choices_for(self, dbfield) to cover that. Yes, this means adding a lot of potential methods to ModelAdmin (though note that since they are dynamically looked up we don't have to add any real new methods to the actual class itself). I think that's fine - it makes for an API that is clean, powerful and extremely easy to understand. I realise that some of the above could be mocked up just by writing a custom formfield_for_dbfield method without patching newforms-admin at all. I plan to do that as a proof of concept. 3. Make it easier to include custom CSS and JavaScript By far the easiest way to tweak the admin is with a bit of unobtrusive CSS and JavaScript. We're using jQuery a lot for this (to great effect; for example, we've got a really nice drag-and-drop reordering interface that was added entirely as an unobtrusive enhancement), but it's still a bit of a pain to add custom CSS / JS. Here's the pattern at the moment: class AdminFormWithMedia(forms.ModelForm): class Media: js = ('blah/blah/blah.js',), css = { all': ('blah/blah.css',) } class ArticleAdmin(admin.ModelAdmin): form = PageFormWithMedia That's quite a lot of boilerplate just to add some CSS and JS, and it's weird to be putting it on the form rather than just specifying it for a template (not to mention this method doesn't let you add custom CSS/JS to the changelist page). Solving the custom template problem above would solve this as well. A few other things we've found difficult: * Customising the admin homepage (without writing a new one from scratch) * Changing the application labels that appear in the admin homepage - we needed to do this and it ended up being a complete nightmare (our end users don't want to see an interface full of obscure terms like gcap_sectional_revisions). * Making some fields read-only in some admin screens (again, reasonably well addressed by easier custom widgets above) The thing is, none of these problems are particularly difficult to address. As it stands, newforms-admin customisation is 90% of the way there - adding just a few more hooks would solve almost all of the above issues. I would be delighted to produce patches for these, but I thought it best to air the ideas on the mailing list first. Cheers, Simon --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~----------~----~----~----~------~----~------~--~---