如何在 Django 的 ModelForm 中使用请求
Posted
技术标签:
【中文标题】如何在 Django 的 ModelForm 中使用请求【英文标题】:How to use the request in a ModelForm in Django 【发布时间】:2012-02-09 02:54:28 【问题描述】:我想创建一个查询集,将当前用户用作 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)
它有效并且代码在表单中。现在我不确定这是不是最好的解决方案,是否可以改进?
【问题讨论】:
Django 文档:Models and request.user 【参考方案1】:不,请求不会传递给 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
【讨论】:
你是对的,它有效。我想知道是否可以将代码放入表单中,只是为了组织目的和全局清洁。 是的,这是可能的,而且为了保持您的视图代码干净,这通常是一个好主意。我已经更新了一个示例。【参考方案2】:将 AdamKG answer 扩展到基于类的视图 - 覆盖 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
然后在表格中:
from django.forms import ModelForm
class BookSubmitForm(ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super().__init__(*args, **kwargs)
...
【讨论】:
以上是关于如何在 Django 的 ModelForm 中使用请求的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Modelform 的网格中呈现 Django CheckoxInput?
如何使用 Modelform 和 jquery 在 django 中获取相互依赖的下拉菜单?
如何在 Django 中向 ModelForm 添加非模型字段?