How to create user-specific admins in Django

The newForms admin branch of Django officially landed in trunk a few weeks ago. Not only does this allow for the awesome django.contrib.admin application to be more customizable, it also solves handily a problem I ran into for an upcoming project: Creating a user-specific Django admin where users see only the objects they create.

Project intentions

My latest Django project involves creating a basic content management system (CMS) that I can use as a hands-on example for a journalism class I’m teaching at The University of Tennessee this fall.

The class, Managing Newspaper Web sites, will cover basic concepts for managing a modern newsroom where a CMS is a vital part of the publishing process. One assignment, for example, will require students to take a story written for print, and edit it for the Web as they enter it into a CMS.

To accomplish this goal, I plan to build a basic models for stories, categories and photos that I hope will emulate those in Ellington, the Django-based CMS used by newspaper Web sites owned by Scripps (my employer).

Other requirements

But unlike Ellingon, where anyone with the proper access can see everyone else’s stories, I don’t want students to be able to copy another student’s work. A student should see only the objects they save into the database.

Also, this CMS will need to display a generic detail view to show how their HTML — students will learn basic HTML as needed for text formatting — will be rendered on a published story. This template won’t be designed, but will reveal proper use of tags.

Each student will have a login, and I will be a superuser that can see everyone’s work.

Model changes

Credit for the code behind a user-specific admin in Django should be given in this case to comment No. 146694 on Jeff Croft’s blog entry “Top ten things that suck about Django, revisited.”

Here’s what I’m going on my story admin model (using Django trunk with newForms admin):

class StoryAdmin(admin.ModelAdmin):
    def queryset(self, request):
        qs = super(StoryAdmin, self).queryset(request)
        if not request.user.is_superuser:
            qs = qs.filter(author=request.user)
        return qs, StoryAdmin)

You can add this function to any model that needs to be user-specific. For instance, I also want my Photo model, used for uploading story photos, to be user-specific.

After this has been added, you should be able to create new users without superuser access — you could also modify the function to restrict only certain groups — and have them only view what they create, while you as superuser see all objects.

One caveat: I’m certainly no Django expect, so if you have a better way of doing this, please leave a comment, or contact me directly.

Read full article at “Entries for Django tag |”

Leave a comment