如何在 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?

如何在 Django ModelForm 中获取实例

如何使用 Modelform 和 jquery 在 django 中获取相互依赖的下拉菜单?

如何在 Django 中向 ModelForm 添加非模型字段?

使用 Django,如何在模板中动态设置 ModelForm 字段值?

如何使用 Ajax 在 Django 中更新 modelForm