django:如何在ModelForm中访问当前请求用户?

flvtvl50  于 2022-11-18  发布在  Go
关注(0)|答案(5)|浏览(144)

在我的ModelForm实现中,我希望根据当前用户是否为超级用户来执行不同类型的验证检查。我如何访问当前请求用户?

332nm8kg

332nm8kg1#

如果你使用的是基于类的视图(CBV),那么在表单构造函数中传递额外的参数(例如在get_forms_class中)或在form_class中传递额外的参数将不起作用,因为<form> object is not callable将显示出来。
CBV的解决方案是使用get_form_kwargs(),例如:
views.py:

class MyUpdateView(UpdateView):

    model = MyModel
    form_class = MyForm

    # Sending user object to the form, to verify which fields to display/remove (depending on group)
    def get_form_kwargs(self):
        kwargs = super(MyUpdateView, self).get_form_kwargs()
        kwargs.update({'user': self.request.user})
        return kwargs

forms.py:

class MyForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user')  # To get request.user. Do not use kwargs.pop('user', None) due to potential security hole

        super(MyForm, self).__init__(*args, **kwargs)

        # If the user does not belong to a certain group, remove the field
        if not self.user.groups.filter(name__iexact='mygroup').exists():
            del self.fields['confidential']
nc1teljy

nc1teljy2#

可以将用户对象作为表单构造函数中的额外参数传递。
例如:

f = MyForm(user=request.user)

构造函数看起来像:

class MyForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
         self.user = kwargs.pop('user',None)
         super(MyForm, self).__init__(*args, **kwargs)

然后根据需要在clean_XX表单中使用user

taor4pac

taor4pac3#

我的小补充,
我有一个需求,表单的一个模型选择字段依赖于request.user,我花了一段时间才弄明白。
我们的想法是
1.您需要在模型表单类中有一个__init__方法,
1.并从__init__方法的参数中访问request或其他参数,
1.然后需要调用super构造函数来新建窗体类
1.然后设置必填字段的queryset

代码示例

class CsvUploadForm(forms.Form):

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user')
        super(CsvUploadForm, self).__init__(*args, **kwargs)
        self.fields['lists'].queryset = List.objects.filter(user=user)

    lists = forms.ModelChoiceField(queryset=None, widget=forms.Select, required=True)

正如您所看到的,lists变量依赖于当前用户,它可以通过request对象获得,因此我们将字段的queryset设置为null,并在以后从构造函数中动态分配。

查看上述代码中语句的顺序

您可以从视图文件中传递用户变量,如下所示

form = CsvUploadForm(user=request.user)

或使用其他POST、FILE数据,如下所示

form = CsvUploadForm(request.POST, request.FILES, user=request.user)
vd2z7a6w

vd2z7a6w4#

您可以使用示例本身中的示例属性引用用户对象。
例如:self.instance.user

class StatusForm(ModelForm):

    # def __init__(self, *args, **kwargs):
    #     self.user = kwargs.pop('user', None)
    #     super(StatusForm, self).__init__(*args, **kwargs)

    class Meta:
        model = Status
        fields = [
            'user',
            'content',
            'image'
        ]

    def clean_content(self):
        content = self.cleaned_data.get("content", None)
        if len(content) > 240:
            raise ValidationError(f"Hey {self.instance.user.username}, the content is too long")
        return content
mklgxw1f

mklgxw1f5#

当我没有在get_context_data中显式地发送表单时,这对我很有效:
views.py

class MyView(FormView):
    model = MyModel
    form_class = MyForm

    def get_form_kwargs(self):
       kwargs = super(MyView, self).get_form_kwargs()
       kwargs.update({'user': self.request.user})
       return kwargs

form.py

class MyForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
       self.user = kwargs.pop('user')
       super(MyForm, self).__init__(*args, **kwargs)

       if not self.user.groups.filter(name__iexact='t1_group').exists():
          del self.fields['test_obj']

当在get_context_data中显式发送表单时,我们可以使用,这就是forms.Form:
views.py 我的视图(FormView):模型=我的模型表单_类=我的表单

def get_context_data(self, **kwargs):
       context = super(MyView, self).get_context_data(**kwargs)
       context['form'] = self.form_class(self.request.user)
       return context

forms.py

class MyForm(forms.Form):

    def __init__(self, user,*args, **kwargs):
       super(MyForm, self).__init__(*args, **kwargs)

       if not user.groups.filter(name__iexact='t1_group').exists():
          del self.fields['test_obj']

相关问题