Django admin:仅在更改表单上排除字段

2024-05-29 10:02:17 发布

您现在位置:Python中文网/ 问答频道 /正文

是否有方法检测模型中的信息是否正在添加或更改。

如果有此信息,则可以用于排除字段。

一些伪代码来说明我在说什么。

class SubSectionAdmin(admin.ModelAdmin):
    if something.change_or_add = 'change':
        exclude = ('field',)
    ...

谢谢


Tags: or方法代码模型add信息fieldif
3条回答
class SubSectionAdmin(admin.ModelAdmin):
    # ...
    def change_view(self, request, object_id, extra_context=None):       
        self.exclude = ('field', )
        return super(SubSectionAdmin, self).change_view(request, object_id, extra_context)

orwellian的回答将使整个subsectionadminisingleton更改其exclude属性。

确保在每个请求的基础上排除字段的一种方法是执行以下操作:

class SubSectionAdmin(admin.ModelAdmin):
    # ...
    def get_form(self, request, obj=None, **kwargs):
        """Override the get_form and extend the 'exclude' keyword arg"""
        if obj:
            kwargs.update({
                'exclude': getattr(kwargs, 'exclude', tuple()) + ('field',),
            })
        return super(SubSectionAdmin, self).get_form(request, obj, **kwargs)

它只会通知表单排除这些额外字段。

不确定给定一个被排除在外的必需字段,这将如何表现。。。

设置self.exclude就像@steve pike提到的那样,使整个SubSectionAdmin单例更改其exclude属性。 singleton是一个类,每当类被实例化时,它都将重用同一个实例,因此只有在第一次使用构造函数时才创建一个实例,随后使用构造函数将返回同一个实例。请参阅wiki page以获取更不规范的描述。 这意味着,如果编写代码以在更改时排除字段,则意味着如果首先添加项,则该字段将在其中,但如果打开要更改的项,则该字段将在您接下来访问“添加”页时被排除。

实现每个请求行为的最简单方法是使用get_fields并对obj参数进行测试,如果要添加对象,则使用None;如果要更改对象,则使用对象实例。Django 1.7提供了get_fields方法。

class SubSectionAdmin(admin.ModelAdmin):
    def get_fields(self, request, obj=None):
        fields = super(SubSectionAdmin, self).get_fields(request, obj)
        if obj:  # obj will be None on the add page, and something on change pages
            fields.remove('field')
        return fields

更新:

请注意,get_fields可能返回元组,因此您可能需要将fields转换为列表以删除元素。 如果试图删除的字段名不在列表中,则也可能会遇到错误。因此,在某些情况下,当您有其他排除字段的因素时,最好使用列表理解来构建一组排除并删除:

class SubSectionAdmin(admin.ModelAdmin):
    def get_fields(self, request, obj=None):
        fields = list(super(SubSectionAdmin, self).get_fields(request, obj))
        exclude_set = set()
        if obj:  # obj will be None on the add page, and something on change pages
            exclude_set.add('field')
        return [f for f in fields if f not in exclude_set]

或者,您也可以在get_fieldsets方法中生成结果的deepcopy,在其他用例中,该方法可以让您访问更好的上下文来排除内容。很明显,如果需要对字段集名称执行操作,这将非常有用。另外,如果实际使用字段集,这是唯一的方法,因为这将省略对get_fields的调用。

from copy import deepcopy

class SubSectionAdmin(admin.ModelAdmin):
    def get_fieldsets(self, request, obj=None):
        """Custom override to exclude fields"""
        fieldsets = deepcopy(super(SubSectionAdmin, self).get_fieldsets(request, obj))

        # Append excludes here instead of using self.exclude.
        # When fieldsets are defined for the user admin, so self.exclude is ignored.
        exclude = ()

        if not request.user.is_superuser:
            exclude += ('accepted_error_margin_alert', 'accepted_error_margin_warning')

        # Iterate fieldsets
        for fieldset in fieldsets:
            fieldset_fields = fieldset[1]['fields']

            # Remove excluded fields from the fieldset
            for exclude_field in exclude:
                if exclude_field in fieldset_fields:
                    fieldset_fields = tuple(field for field in fieldset_fields if field != exclude_field)  # Filter
                    fieldset[1]['fields'] = fieldset_fields  # Store new tuple

        return fieldsets

相关问题 更多 >

    热门问题