Customizing the Admin Forms
There is a lot written on how to customize the design and general data on the admin interface. In this post I will ask a little bit separate question: How can you customize only a small portion of the form generated by the admin app?
The solution is kind of easy. As an example I will take a code snippet from the byteflow blogging engine. Our problem was that the blog engine automatically registers everyone who comments on your blog. As a result, after a couple of comments it is rather difficult to find yourself in the list of authors when you would like to write a new post.
The model-based solution
Our Post model defined the author field as
author = models.ForeignKey(User, related_name='posts')
We can achieve a restricted selection by simply adding a limit_to parameter to ForeignKey. So we would get
author = models.ForeignKey(User, related_name='posts', limit_choices_to={'is_staff: True'})
But then we get the idea of having the actual user preselected! This is a simple feature, but still saves you some seconds on really boring administrative tasks.
The admin inheritance solution
If you have a look at an admin interface definition it is obvious that you could use inheritance, and simply overwrite only one method. The one that generates the form!
class PostAdmin(admin.ModelAdmin):
By checking the original ModelAdmin class it was easy to find out that the form is actually created by its get_form method. So you just have to define this same method in your PostAdmin class, and customize the form as you like!
def get_form(self, request, obj=None, **kwargs):
form = super(PostAdmin, self).get_form(request, obj, **kwargs)
form.base_fields['author'] = forms.ModelChoiceField(label=_('Author'), queryset=User.objects.filter(is_staff=True), initial=request.user.pk)
return form
As you can see, the first line just calls real get_form method. While the modifies it according to our needs. Here we actually recreate the author field, but probably (someone more literate in the newforms library) could simply set the initial value as well.