基本思想是能够基于模型权限检查隐藏一些表单字段(使用基于类的通用视图)。很明显,我可以覆盖视图的get
和post
来检查表单权限并构造表单,但是没有更简洁的方法来实现这一目标吗?
到目前为止,视图和表单非常简单
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
)添加/删除字段。
因此,直接的方法是在视图上重载get
和post
,执行检查并实例化表单。但它有点重复现有的django行为(即管理员视图将request
传递给get_form
)。那么,有没有更清洁的方法来实现它?
答案 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.exclude
和Meta.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]