multiblog - a simple example of row-level permissions in the admin

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# models.py
from django.db import models

class Entry(models.Model):
    title = models.CharField(max_length=255)
    body = models.TextField()
    created = models.DateTimeField(auto_now_add = True)
    author = models.ForeignKey('auth.User')
    
    def __unicode__(self):
        return self.title
    
    class Meta:
        verbose_name_plural = 'entries'

# admin.py
from django.contrib import admin
from models import Entry

class EntryAdmin(admin.ModelAdmin):
    list_display = ('title', 'created', 'author')
    list_filter = ('author',)
    exclude = ['author']
    
    def queryset(self, request):
        qs = super(EntryAdmin, self).queryset(request)
        if request.user.is_superuser:
            return qs
        else:
            return qs.filter(author = request.user)
    
    def save_model(self, request, obj, form, change):
        obj.author = request.user
        obj.save()
    
    def has_change_permission(self, request, obj=None):
        if not obj:
            return True # So they can see the change list page
        if request.user.is_superuser or obj.author == request.user:
            return True
        else:
            return False
    
    has_delete_permission = has_change_permission    

admin.site.register(Entry, EntryAdmin)

More like this

  1. Support for permissions for anonymous users in django ModelBackend by jb 2 years, 5 months ago
  2. Row-Level, URL-based permissions for FlatPages by bradmontgomery 4 years, 10 months ago
  3. permission_required with multiple permissions by uswaretech 4 years, 9 months ago
  4. AdminPeepingMiddleware by buriy 6 years, 7 months ago
  5. Permission Required Middleware by mattgrayson 5 years, 4 months ago

Comments

memyselfandi (on September 18, 2008):

this works fine, but suppose you have the following case that your initial model has a foreign key to a different model, then filtering does not work. The normal user will still see all entries from all other users. In this case (assuming you use the same admin model that you proposed for both models) a normal user will only be able to see his entries and projects, but when he creates a new entry, he can choose from all projects, not only his own. Is there a way to submit a filter to ForeigKey?

class Entry(models.Model):
    title = models.CharField(max_length=255)
    body = models.TextField()
    created = models.DateTimeField(auto_now_add = True)
    author = models.ForeignKey('auth.User')
    project = models.ForeignKey(Project)

class Project(models.Model):
    title = models.CharField(max_length=255)
    body = models.TextField()
    created = models.DateTimeField(auto_now_add = True)
    author = models.ForeignKey('auth.User')

[HTML_REMOVED][HTML_REMOVED]

#

atozand1to10 (on May 8, 2009):

Facing the same problem as above. Has anyone figured it out yet? Please share.

#

mambo (on June 1, 2009):

Add following methods to your ModelAdmin and define filters for form and queryset.

class ModelAdmin(admin.ModelAdmin):
    def queryset(self, request):
        queryset = super(ModelAdmin, self).queryset(request)
        if request.user.is_superuser:
            return queryset
        return self.filter_user_queryset(queryset, request)

    def get_form(self, request, obj=None):
        form = super(ModelAdmin, self).get_form(request, obj)
        if request.user.is_superuser:
            return form
        return self.filter_user_form(form, request)

    def get_changelist_form(self, request, **kwargs):
        form = super(ModelAdmin, self).get_changelist_form(request, **kwargs)
        if request.user.is_superuser:
            return form
        return self.filter_user_form(form, request)

    def get_changelist_formset(self, request, **kwargs):
        formset = super(ModelAdmin, self).get_changelist_formset(request, **kwargs)
        if request.user.is_superuser:
            return formset
        formset.form = self.filter_user_form(formset.form, request)
        return formset

    def filter_user_form(self, form, request):
        return form

    def filter_user_queryset(self, queryset, request):
        return queryset

class MyAdmin(ModelAdmin):
    def filter_user_form(self, form, request):
        return form.base_fields['redirect'].queryset = Domain.objects.filter(userindomain__user = request.user)

    def filter_user_queryset(self, queryset, request):
        return queryset.filter(userindomain__user = request.user)

#

jheasly (on January 8, 2010):

@mambo;

About this line:

return form.base_fields['redirect'].queryset = Domain.objects.filter(userindomain__user = request.user)

... what is "userdomain"? A relation of some kind in the model "Domain"?

#

(Forgotten your password?)