【问题标题】:How to process a form (via get or post) using class-based views?如何使用基于类的视图处理表单(通过 get 或 post)?
【发布时间】:2012-02-12 18:52:53
【问题描述】:

我正在尝试学习基于类的视图,因为详细视图或列表视图并不复杂。

我有一个搜索表单,我只是想看看我是否发送查询以显示结果。

这是函数代码(不是我的,来自django书):

def search_page(request):
    form = SearchForm()
    bookmarks = []
    show_results = False
    if 'query' in request.GET:
        show_results = True
        query = request.GET['query'].strip()
        if query:
            form = SearchForm({'query': query})
            bookmarks = Bookmark.objects.filter(title__icontains=query)[:10]


    show_tags = True
    show_user = True

    if request.is_ajax():
        return render_to_response("bookmarks/bookmark_list.html", locals(), context_instance=RequestContext(request))
    else:
        return render_to_response("search/search.html", locals(), context_instance=RequestContext(request))

忽略 ajax 事实(只是暂时让问题更容易),我如何将其转换为基于类的视图?

我很快尝试了这样的事情:

class SearchPageView(FormView):
    template_name = 'search/search.html'

    def get(self, request, *args, **kwargs):
        form = SearchForm()
        self.bookmarks = []
        self.show_results = False
        if 'query' in self.request.GET:
            self.show_results = True
            query = self.request.GET['query'].strip()
            if query:
                form = SearchForm({'query': query})
                self.bookmarks = Bookmark.objects.filter(title__icontains=query)[:10]
        return super(SearchPageView, self).get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(SearchPageView, self).get_context_data(**kwargs)
        context.update({
            'show_tags': True,
            'show_user': True,
            'show_results': self.show_results,
            'bookmarks': self.bookmarks
        })
        return context

不起作用,我得到一个:“'NoneType' 对象不可调用”

很公平,我今天从这些东西开始。

那么,有什么方法可以创建一个基于类的视图来管理一个获取(如果需要的话也可以是一个帖子)请求?

我还有一个例子:

@render_to('registration/register.html')
def register_page(request):
    if request.method == 'POST':
        form = RegistrationForm(request.POST)
        if form.is_valid():
            user = User.objects.create_user(
                username=form.cleaned_data['username'],
                password=form.cleaned_data['password1'],
                email=form.cleaned_data['email']
            )
            return HttpResponseRedirect('/accounts/register/success/')
    else:
        form = RegistrationForm()
    return locals()

这会以与第一个相同的方式“转换”吗?或者他们扩展了不同的视图?

我很困惑。不知道第一个是ProcessFormView,第二个是FormView还是什么。

谢谢。

编辑: 我的解决方案是:

class SearchPageView(FormView):
    template_name = 'search/search.html'

    def get(self, request, *args, **kwargs):
        self.bookmarks = []
        self.show_results = False
        form = SearchForm(self.request.GET or None)
        if form.is_valid():
            self.show_results = True
            self.bookmarks = Bookmark.objects.filter(title__icontains=form.cleaned_data['query'])[:10]

        return self.render_to_response(self.get_context_data(form=form))


    def get_context_data(self, **kwargs):
        context = super(SearchPageView, self).get_context_data(**kwargs)
        context.update({
            'show_tags': True,
            'show_user': True,
            'show_results': self.show_results,
            'bookmarks': self.bookmarks
        })
        return context

我把这个留给有同样问题的人:)

【问题讨论】:

  • 复制和粘贴'NoneType' object is not callable" 不是很有帮助。如果您查看回溯中的行号,您可以看到是哪一行代码引发了异常,这可能有助于您自己修复它。
  • 问题更新了,你说得对,我得睡觉了,我想我需要指定我的表单类,是的,你说得对。

标签: django django-class-based-views


【解决方案1】:

注意,这里的答案 (Updating context data in FormView form_valid method?) 解决了这个问题:

class ContextFormView(FormView):
    template_name = 'some_template.html'
    success_url = '...'
    form_class = ClassOfTheForm

    def get(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        context = self.get_context_data(**kwargs)
        context['form'] = form
        return self.render_to_response(context)

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        if form.is_valid():
            return self.form_valid(form, **kwargs)
        else:
            return self.form_invalid(form, **kwargs)


    def form_invalid(self, form, **kwargs):
        context = self.get_context_data(**kwargs)
        context['form'] = form
        # here you can add things like:
        context[show_results] = False
        return self.render_to_response(context)

    def form_valid(self, form, **kwargs):
        context = self.get_context_data(**kwargs)
        context['form'] = form
        # here you can add things like:
        context[show_results] = True
        return self.render_to_response(context)

这对我来说很完美。 (与此问题相同)

如上所述,这不是我的解决方案,如果您想给某人积分,请转到链接中的答案并给此人积分! (Updating context data in FormView form_valid method?)

【讨论】:

  • 我可以用这种方法将通用ListViewFormView 组合在一个页面上吗?这样我就可以将数据库中的记录列表 AND 全部放在一个模板页面上。只需用FormView 替换ListView 类,然后覆盖get 方法不起作用,只有表单作为上下文传递,视图作为<scraping.views.HomePageView object at 0x109ebd070> 传递
【解决方案2】:

FormView 类的默认行为是为GET 请求显示未绑定的表单,并为POST(或PUT)请求绑定表单。如果绑定的表单有效,则调用form_valid 方法,该方法简单地重定向到成功url(由success_url 属性或get_success_url 方法定义。

这与示例非常匹配。你需要重写form_valid方法来创建新的User,然后调用超类方法重定向到成功的url。

class CreateUser(FormView):
    template_name = 'registration/register.html'
    success_url = '/accounts/register/success/'
    form_class = RegistrationForm

    def form_valid(self, form):
        user = User.objects.create_user(
                username=form.cleaned_data['username'],
                password=form.cleaned_data['password1'],
                email=form.cleaned_data['email']
        )
        return super(CreateUser, self).form_valid(form)

您的第一个示例与FormView 的流程不太匹配,因为您没有处理带有POST 数据的表单,并且当表单有效时您不执行任何操作。

我可能会尝试扩展TemplateView,并将所有逻辑放入get_context_data。 一旦你开始工作,你可以将解析 GET 数据并将书签返回到它自己的方法中的代码分解。您可以查看扩展 ListView,但我认为除非您想对结果进行分页,否则没有任何真正的优势。

【讨论】:

  • 这个例子的工作就像一个魅力(改变属性的名称:P)但我仍然认为第一个例子需要一个正确的基于类的视图表示。
  • 你能帮帮我吗?当您定义用户对象时,它在 form_valid 方法之后去哪里,这对我来说就像魔术一样。
  • @skzd 恐怕我不明白你的意思。除非我上面的回答有错误,否则请打开一个新问题,而不是在这里添加评论。
  • @skzd,form_valid运行后函数退出,页面重定向到success_url。就是这样,直到发生更多的用户交互。
猜你喜欢
  • 1970-01-01
  • 2022-01-10
  • 2017-11-07
  • 1970-01-01
  • 2016-12-05
  • 2015-04-20
  • 2020-06-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多