Django: 带有post()方法的ListView?

13 投票
1 回答
28956 浏览
提问于 2025-04-17 20:15

我正在尝试在Django的类视图中处理两个表单。这个网站有一个叫做form的表单(基于GET请求),用于缩小列表视图的结果范围,还有一个第二个表单status_form(基于POST请求)。

这两个表单都是必须的,因为列表视图会返回一系列项目。Form让用户可以限制选择,而status_form则允许用户通过一个弹出表单标记不正确的项目(所以它需要在同一个模板中)。

我遇到的问题是,ListView没有post这个方法,而FormView有。我的类List同时继承了这两个类,但当我执行这个类时,出现了错误信息:

属性错误:'List'对象没有属性'status_form'

我应该如何修改我的实现,以便通过post方法处理第二个表单呢?

class List(PaginationMixin, ListView, FormMixin):
    model = ListModel
    context_object_name = 'list_objects'
    template_name = 'pages/list.html'
    paginate_by = 10 #how may items per page

    def get(self, request, *args, **kwargs):
        self.form = ListSearchForm(self.request.GET or None,)
        return super(List, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.status_form = StatusForm(self.request.POST or None)
        if self.status_form.is_valid():
            ...
        else:
            return super(List, self).post(request, *args, **kwargs)

    def get_queryset(self):
        # define the queryset
        ...
        # when done, pass to object_list
        return object_list

    def get_context_data(self, **kwargs):
        context = super(List, self).get_context_data(**kwargs)
        context.update(**kwargs)
        context['form'] = self.form
        context['status_form'] = self.status_form # Django is complaining that status_form is not existing, result since the post method is not executed
        return context

1 个回答

7
# Django is complaining that status_form does not exist,
# result since the post method is not executed
context['status_form'] = self.status_form

因为你一开始没有定义 self.status_from。你是在 get_context_data 里定义的,所以只能在那里面访问到它。

你可以在你的 post 方法中通过 get_context_data 来访问你的对象。

context = self.get_context_data(**kwargs)
status_form = context['status_form']

另外,你可以直接在 post 方法里定义你的 status_form,而不需要从 selfget_context_data 中获取。

可以重新设计你的视图,把每个表单的处理分开到不同的视图中,然后把它们联系起来。

视图重新设计:

简单来说,让每个视图只做一件事。你可以创建一个专门处理 status_form 的视图,给它起个名字,比如 StatusFormProcessView,然后在你的 List 视图中在 post 方法里返回它。

class List(ListView);
    def post(self, request, *args, **kwargs):
        return StatusFormView.as_view()(request) # What ever you need be pass to you form processing view

这只是一个例子,实际应用还需要更多工作。

再举个例子;在我的网站首页,我有一个搜索表单。当用户通过 POSTGET 提交搜索表单时,搜索的处理并不在我的 IndexView 中,而是我在一个单独的视图中处理整个表单。如果表单需要在 GET 方法中处理,我会重写 get() 方法;如果表单需要在 POST 方法中处理,我会重写 post() 方法,把 search_form 的数据发送到负责处理 search_form 的视图。

评论回复

status_form = context['status_form']

难道不应该是

context['status_form'] = status_form

在我创建它之后吗?

你想从 context 中获取 status_form,所以你需要

status_form = context['status_form']

无论如何,你的表单数据在 self.request.POST 中是可以获取的。

撰写回答