根据条件在 django admin 中禁用或只读非模型字段

Make non-model field disabled or readonly in djnago admin based on condition

我有它的模型、管理员和表单。但是我的表单中有一个字段不在模型中,我正在对该字段执行一些自定义操作。

我希望此字段对没有某些权限的用户只读或隐藏或禁用,但 django 不允许我动态设置任何这些属性。

我的模特:

class PromocodePool(TimeStampedModel):
    start = models.DateTimeField()
    end = models.DateTimeField(null=True, blank=True)

表格:

class PromocodePoolForm(forms.ModelForm):
    promocodes = forms.FileField(widget=AdminFileWidget, required=False) # this field is non-model

    class Meta:
        model = PromocodePool
        fields = '__all__'

管理员:

@admin.register(PromocodePool)
class PromocodePoolAdmin(admin.ModelAdmin):
    form = PromocodePoolForm

    list_display = ("get_start", "get_end")
    readonly_fields = (<some fields, tuple>)

    @admin.display(description="Start date")
    def get_start(self, obj):
        return _date(obj.start, formats.DATE_FORMAT)

    @admin.display(description="Start date")
    def get_end(self, obj):
        return _date(obj.end, formats.DATE_FORMAT)

    def get_readonly_fields(self, request, obj=None):
        if not request.user.has_perm("promocode.custom_permission"):
            self.readonly_fields += ("promocodes",) # this doesn't work
        return self.readonly_fields

我收到此错误: Unable to lookup 'promocodes' on PromocodePool or PromocodePoolAdmin or PromocodePoolForm

顺便说一句,如果我重命名我的表单,错误文本保持不变,因为真正的“完成”表单是通过 django 的 ModelFormMetaclass 生成的,并且称为 PromocodePoolForm,而这个表单不是我上面描述的表单。

有什么方法可以动态禁用这个字段吗?

如果重要,我使用 python 3.8 和 Django 3.2.6


谢谢 我进一步搜索并解决了我的问题。

我制作了两个表格 classes 而不是我以前的一个


class PromocodePoolForm(forms.ModelForm):
    promocodes = forms.FileField(widget=AdminFileWidget, required=False, disabled=True)

    # no validation/processing for this non-model field in this class
    # just disabled field

    class Meta:
        model = PromocodePool
        fields = '__all__'

class PromocodePoolFormNotDisabled(PromocodePoolForm):
    promocodes = forms.FileField(widget=AdminFileWidget, required=False)

    # all validation/processing for non-model field is in this class now

并将此方法添加到管理 class 而不是 get_readonly_fields

@admin.register(PromocodePool)
class PromocodePoolAdmin(admin.ModelAdmin):
    form = PromocodePoolForm
    
    ...
    
    def get_form(self, request, obj=None, change=False, **kwargs):
        if request.user.has_perm("promocode.custom_permission"):
            self.form = PromocodePoolFormNotDisabled
        return super().get_form(request, obj, change, **kwargs)

它就像一个魅力:如果用户没有权限,他会得到带有禁用字段的表单,否则他会得到正常的。

看来,您可以覆盖 get_forms 方法,在那里检查用户自定义权限,并返回您的自定义表单。我不知道,当然,这是一个很好的方法,但在我的情况下它有效)