【问题标题】:Understanding django admin readonly_fields了解 django admin readonly_fields
【发布时间】:2012-01-23 17:41:15
【问题描述】:

我创建了一些代码来区分 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 块中为管理员用户添加了一个额外的 if 语句,一切都会按预期工作。

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

为什么会这样?那里发生了什么?

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

据我了解 request.user.groups.all() 应该返回 当前登录 用户所属的所有组。如果不同 IP 和会话上的另一个用户与此 if 块匹配,Django 从哪里获取所有字段(只读)?

【问题讨论】:

    标签: python django django-admin


    【解决方案1】:

    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 块中指定所有应该只读非超级用户的字段。

    【讨论】:

    • 谢谢,按说明工作。我已经使用了 get_readonly_fields 但我必须盲目地不要将它用于此目的。
    • 该示例未通过 obj 参数,但始终将其设置为 None。应该是:return super(MyModelAdmin, self).get_readonly_fields(request, obj)
    • @seddonym:很好。现在修好了。只花了一年半的时间就有人注意到了;)
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2014-01-24
      • 1970-01-01
      • 2016-11-15
      • 1970-01-01
      • 2014-05-07
      • 1970-01-01
      • 1970-01-01
      • 2017-03-19
      • 1970-01-01
      相关资源
      最近更新 更多