2012-01-23 221 views
3

我创建了一些代码来区分Django admin中的两个用户组,导致只显示所有字段或只显示其中一部分,它们直接在ModelAdmin类中设置。了解django管理员readonly_fields

起初这里是代码:

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) 

我的组之间分配,并设置相应的字段。如果两个组的用户没有同时登录,那么一切正常! 'readonly'用户登录后,adminuser将只读取所有字段。

我检查提供了一个解决方案也: 如果我把一个额外的,如果为块内的一切管理用户的语句按预期工作。

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

这是为什么,那里发生了什么?

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

从我的理解request.user.groups.all()应返回所有组当前登录用户所属。 Django从其他IP和会话中的其他用户是否匹配此块(如果有块),从哪里获得allfields(只读)?

回答

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') 

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

+0

谢谢,作为解释。我已经使用了get_readonly_fields,但是我必须盲目不要将其用于此目的。 – normic

+0

该示例未通过obj参数,但始终将其设置为None。应该是: return super(MyModelAdmin,self).get_readonly_fields(request,obj) – seddonym

+0

@seddonym:良好的捕获。现在修复。只有一年半才有人注意到;) –

1

由于Django Admin中的字段在重新启动Web服务器时第一次运行后正在设置(即缓存)。你可以通过重新声明readonly_fields元组来解决它。类似这样的(未经测试):

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