我想创建一个查询集,其中当前用户用作ModelForm中的过滤器:
class BookSubmitForm(ModelForm):
book = forms.ModelChoiceField(queryset=Book.objects.filter(owner=request.user),)
...
Django是否将请求传递给表单?这是好习惯吗?我该如何使用该请求? (当然没有定义名称请求)
编辑:
我尝试了另一个解决方案,即在视图中调用表单并传递请求:
form = BookSubmitForm(request)
然后以我使用的形式:
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)
它有效并且代码在表单中。现在我不确定它是最好的解决方案,可以改进吗?
答案 0 :(得分:32)
不,请求未传递给ModelForm。您需要在视图中执行以下操作:
form = BookSubmitForm()
form.fields['book'].queryset = Book.objects.filter(owner=request.user)
# pass form to template, etc
正如您所说,将它封装在Form对象中通常更加清晰,特别是如果您有多个需要过滤查询集的字段。要执行此操作,请覆盖表单的__init__()
并让其接受request
的kwarg:
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)
然后只需在视图中实例化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
答案 1 :(得分:2)
将AdamKG answer扩展到基于类的视图 - 覆盖get_form_kwargs
方法:
class PassRequestToFormViewMixin:
def get_form_kwargs(self):
kwargs = super(PassRequestToFormViewMixin, self).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
然后以表格形式:
from django.forms import ModelForm
class BookSubmitForm(ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(BookSubmitForm, self).__init__(*args, **kwargs)
...