是否可以基于权限检查隐藏/创建只读表单字段

时间:2013-04-15 23:39:35

标签: django django-forms

基本思想是能够基于模型权限检查隐藏一些表单字段(使用基于类的通用视图)。很明显,我可以覆盖视图的getpost来检查表单权限并构造表单,但是没有更简洁的方法来实现这一目标吗?

到目前为止,视图和表单非常简单

class UserProfileUpdateView(UpdateView):
    model = UserProfile
    template_name = "profile/update.html"
    form_class = UserProfileForm


class UserProfileForm(forms.ModelForm):
def __init__(self, can_change_position=False, can_change_manager=False, *args, **kwargs):
    super(UserProfileForm, self).__init__(*args, **kwargs)
    self._process_permission('position', can_change_position)
    self._process_permission('manager', can_change_manager)

def _process_permission(self, field, permitted):
    if permitted:
        self.fields.append(field)

class Meta:
    model = UserProfile
    fields = ['field1', 'field2', 'field3', ...]

我是否遗漏了一些明显的东西,或者只是按照错误的方式?

更新看起来我的意图不明确。我发布的代码中存在错误,因此到目前为止给出的答案是如何修复错误。我已经修复了它,但问题不在于如何在运行时添加/删除表单上的字段(很明显)。问题是,有没有办法使用基于类的通用视图基于request值(例如request.user)添加/删除字段。

因此,直接的方法是在视图上重载getpost,执行检查并实例化表单。但它有点重复现有的django行为(即管理​​员视图将request传递给get_form)。那么,有没有更清洁的方法来实现它?

2 个答案:

答案 0 :(得分:0)

是的,您的__init__方法是在__new__方法之后调用的,它实际上使用了'Meta.exclude'属性。 (当动态类魔法的这种声明属性发生时)

查看django source第198行。 所以在运行时你已经拥有了所有的实例变量。

类似问题的解决方案,我在这里发布:

CSV upload with no set format before upload

希望有所帮助

答案 1 :(得分:0)

名为base_fields的属性在表单类本身上设置,在您的情况下为UserProfileForm。当您创建此表单的实例,即UserProfileForm()时,在表单实例上设置名为fields的属性,该表单实例是表单类上可用的base_fields的副本。

在元类中设置了base_fields,通常你不想改变元类。此外,Meta.excludeMeta.fields在元类“__new__中使用,因此在表单__init__中更改它们不会产生任何影响。

因此,您可以做的是从fields中的表单实例的属性__init__中删除您不想要的字段。

代码:

class UserProfileForm(forms.ModelForm):
    def __init__(self, can_change_position=False, can_change_manager=False, *args, **kwargs):
        super(UserProfileForm, self).__init__(*args, **kwargs)
        self._process_permission('position', can_change_position)
        self._process_permission('manager', can_change_manager)         

    def _process_permission(self, field, permitted):
        if not permitted and field in self.fields:
            del self.fields[field]