在管理员中使用带有@property的模型的get_readonly_fields

时间:2016-04-13 03:49:39

标签: django django-admin

我对以下内容感到困惑:

models.py

class MyModel(models.Model):
    ...
    @property
    def xyz(self):
        return ...

admin.py:

class MyModelAdmin(admin.ModelAdmin):
    readonly_fields = ("xyz",)
    ...
    def get_readonly_fields(self, request, obj=None):
        """ As per http://stackoverflow.com/a/13818017/1149759 """
        if <some condition>:
            return [f.name for f in self.model._meta.fields]
        return self.readonly_fields

如果满足<some condition>,则此模型的管理页面将失败,并显示:

Unknown field(s) (xyz) specified for MyModel. 
Check fields/fieldsets/exclude attributes of class MyModel.

我尝试重构模型和管理代码以使xyz()不是属性,但同样的错误也以同样的方式发生。

甚至尝试单步执行内部Django代码。它在这条线上失败了:

lib/python2.7/site-packages/django/contrib/admin/options.py(640)get_form()
-> return modelform_factory(self.model, **defaults)

{'fields': [..., 'xyz', ...], 
  'formfield_callback': <functools.partial object at 0x104a024c8>, 
  'form': <class 'django.forms.widgets.ModelForm'>, 
  'exclude': [<a long list of fields that does not include xyz>]}

感谢您提供的任何见解。

更新

  • xyz删除readonly_fields并不能解决问题
  • 根据以下评论尝试完全删除readonly_fields。以下也没有用:

def get_readonly_fields(self, request, obj=None): if <whatever>: return [f.name for f in self.model._meta.fields] return ['xyz', ...]

经过额外测试后,我觉得get_readonly_fields无法在此型号上运行!

class MyModelAdmin(admin.ModelAdmin):
    # readonly_fields = ("xyz",) # Removed this field to test
    ...
    def get_readonly_fields(self, request, obj=None):
        return [] # Removed all the logic 

前面的仍然会引发Unknown fields specified的{​​{1}} - 以及模型中的以下两个字段!

xyz

2 个答案:

答案 0 :(得分:0)

属性与字段不同。您已将xyz定义为属性,Django Admin不支持将其编辑为可编辑的属性。只有模型上的字段可以是管理员的readonly_fields属性的成员。您应该发现xyz不是self.model._meta.fields的成员,因此永远不会被get_readonly_fields返回。

您还应该包含 readonly_fieldsget_readonly_fields

答案 1 :(得分:0)

似乎让这个工作的唯一方法是将xyz显式添加到只读字段列表中。

class MyModelAdmin(admin.ModelAdmin):
    readonly_fields = ("xyz", ...)
    ...
    def get_readonly_fields(self, request, obj=None):
        if <condition>:
            ro = [f.name for f in self.model._meta.fields]
            ro.append('xyz') # <=============
            return ro
        return self.readonly_fields