如何在Django中的ModelForm中使用该请求

Bas*_*ian 21 forms django

我想创建一个查询集,其中当前用户用作ModelForm中的过滤器:

class BookSubmitForm(ModelForm):
    book = forms.ModelChoiceField(queryset=Book.objects.filter(owner=request.user),)
...
Run Code Online (Sandbox Code Playgroud)

Django是否将请求传递给表单?这是好习惯吗?我该如何使用该请求?(当然没有定义名称请求)

编辑:

我尝试了另一个解决方案,即在视图中调用表单传递请求:

form = BookSubmitForm(request)
Run Code Online (Sandbox Code Playgroud)

然后在我使用的形式:

class BookSubmitForm(ModelForm):
    def __init__(self, request, *args, **kwargs):
        super(BookSubmitForm, self).__init__(*args, **kwargs)
        self.fields["library"].queryset = Library.objects.filter(owner=request.user)
Run Code Online (Sandbox Code Playgroud)

它工作,代码在表单中.现在我不确定它是最好的解决方案,它可以改进吗?

Ada*_*mKG 35

不,请求不会传递给ModelForm.您需要在视图中执行以下操作:

form = BookSubmitForm()
form.fields['book'].queryset = Book.objects.filter(owner=request.user)
# pass form to template, etc
Run Code Online (Sandbox Code Playgroud)

正如你所说,这是经常清洁的Form对象中封装这个,特别是如果你有几个领域将需要过滤的查询集.要做到这一点,覆盖表单__init__()并让它接受一个kwarg request:

class BookSubmitForm(ModelForm):
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request")
        super(BookSubmitForm, self).__init__(*args, **kwargs)
        self.fields["book"].queryset = Book.objects.filter(owner=self.request.user)
        self.fields["whatever"].queryset = WhateverModel.objects.filter(user=self.request.user)
Run Code Online (Sandbox Code Playgroud)

然后只要BookSubmitForm在视图中实例化时传递请求:

def book_submit(request):
    if request.method == "POST":
        form = BookSubmitForm(request.POST, request=request)
        # do whatever
    else:
        form = BookSubmitForm(request=request)
    # render form, etc
Run Code Online (Sandbox Code Playgroud)


try*_*bik 5

AdamKG答案扩展到基于类的视图-覆盖get_form_kwargs方法:

class PassRequestToFormViewMixin:
    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

from django.views.generic.edit import CreateView
class BookSubmitCreateView(PassRequestToFormViewMixin, CreateView):
    form_class = BookSubmitForm
# same for EditView
Run Code Online (Sandbox Code Playgroud)

然后是以下形式:

from django.forms import ModelForm
class BookSubmitForm(ModelForm):
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request")
        super().__init__(*args, **kwargs)
        ...
Run Code Online (Sandbox Code Playgroud)