了解django admin readonly_fields

时间:2012-01-23 17:41:15

标签: python django django-admin

我创建了一些代码来区分Django admin中的两个用户组,导致只显示所有字段或仅显示其中的一些字段,这些字段直接在ModelAdmin类中设置。

首先是代码:

class PersonAdmin(admin.ModelAdmin):
    readonly_fields = ('created_at','created_by',)

def get_form(self, request, obj=None, **kwargs):
    if obj:     # we are in edit mode
        if request.user.is_superuser:
            self.readonly_fields = ()
        else:
            for group in request.user.groups.all():
                if str(group) == 'readonlyuser':
                    allfields = tuple(obj._meta.get_all_field_names())
                    self.readonly_fields = allfields

    return super(PersonAdmin, self).get_form(request, obj, **kwargs)

我在组之间划分并相应地设置字段。如果来自两个组的用户没有同时登录,一切正常! 在“只读”用户登录后,管理员也会只读取所有字段。

我的检查也提供了一个解决方案: 如果我在 for 块中为adminuser添加了一个额外的if语句,一切都按预期工作。

if str(group) == 'adminuser':
    self.readonly_fields = PersonAdmin.readonly_fields

为什么那样以及那里发生了什么?

我没有进行特殊的缓存设置,它发生在开发服务器以及带有WSGI的Apache上。

根据我的理解,request.user.groups.all()应该返回当前登录用户所属的所有组。 Django从哪里获取allfields(readonly),如果另一个用户在不同的IP和会话上匹配这个if块?

2 个答案:

答案 0 :(得分:12)

ModelAdmin仅对其收到的所有请求实例化一次。因此,当您定义这样的只读字段时,您将永久地设置它。

只要您运行Django 1.2+,就可以使用get_readonly_fields方法来代替这个目的:

class MyModelAdmin(admin.ModelAdmin):
    ...

    def get_readonly_fields(self, request, obj=None):
        if request.user.is_superuser:
            return super(MyModelAdmin, self).get_readonly_fields(request, obj)
        else:
            return ('created_at', 'created_by')

readonly_fields中删除ModelAdmin属性,或将其设置为 everyone 应该只读的字段。然后,在else块中指定仅对非超级用户应该只读的所有字段。

答案 1 :(得分:1)

因为Django Admin中的字段在重新启动Web服务器后第一次运行后被设置(即缓存)。你可以通过重新声明readonly_fields元组来绕过它。像这样(未经测试):

def get_form(self, request, obj=None, **kwargs):  
    self.readonly_fields = ('created_at','created_by',)
    # ...