Django:在重定向后获取表单后提供验证错误反馈

drc*_*uck 9 django post-redirect-get

我在非 Django Web 开发方面有很好的经验,但是我正在努力寻找一种好的做法来处理当用户在表单中输入无效数据并且我想用他们提交的数据重新显示表单时该怎么做以及显示的表单错误。我有一个包含三个字段的简单表单,这就是我最终使它工作的方式。

def get(self, request) :
    # Check if we have been redirected...
    redirect_html = request.session.pop('form_error_html', False)
    if redirect_html : return HttpResponse(redirect_html)

    old_data = {'title': 'SakaiCar', 'mileage' : 42, 
        'purchase_date': '2018-08-14' }
    form = BasicForm(initial=old_data)
    ctx = {'form' : form}
    return render(request, 'form.html', ctx)

def post(self, request) :
    form = BasicForm(request.POST)
    if not form.is_valid() :
        ctx = {'form' : form}
        html = render_to_string('form.html', ctx, request=request)
        request.session['form_error_html'] = html
        return redirect(request.path)

    # Do something with the valid data..
    return redirect('/')
Run Code Online (Sandbox Code Playgroud)

我的模板非常基础(我喜欢这种简单性):

<p>
  <form action="" method="post">
    {% csrf_token %}
    <table>
    {{ form.as_table }}
    </table>
    <input type="submit" value="Submit">
  </form>
</p>
Run Code Online (Sandbox Code Playgroud)

现在,这种方法种weirds我,因为我是从发送通过会话整个呈现的HTML页面post()get()。但我无法form通过会话将错误发送回get()(那会更漂亮),因为它不会序列化 - 你会得到“'BasicForm'类型的对象不是JSON可序列化的”。

我以不同的方式完成了此操作,将form对象中的错误提取到 a 中list,然后将我自己的错误列表从post()传递到重定向get(),然后更改form.html以显示错误。

{% if errors %}
    {% for error in errors %}
    <p style="color:red">Error in {{ error.label }}: {{ error.message }}</p>
    {% endfor %}
{% endif %}
Run Code Online (Sandbox Code Playgroud)

我没有包含所有的 Python 代码来完成这项工作 - 但你明白了。这感觉更优雅,因为我没有将一团 HTML 放入会话中,但随后错误以不同于正常 Django 表单方式的方式显示。如果我使用的是脆皮形式——那么所有这些脆皮 UI 的优点都不会发挥作用。

我什至想过提取post()代码中的错误并将它们传递给整个get()会话,然后将它们插入到之前的form对象中- 这也会感觉更优雅。如果我感到无聊,我可能会尝试挖掘表单结构并实现它。get()render()

我简直不敢相信 Django 拥有如此强大的内置魔法 - 我不能只return form.post_redirect_get()not form.is_valid代码中说出类似的话。

我想要一种易于解释的可复制模式,并尽可能多地使用 Django UI 元素。

Dan*_*man 3

你误会了。您只应该在成功发布后重定向。在验证失败的帖子上,您根本不重定向,而是重新显示无效的表单 - 这将显示验证错误。

form = BasicForm(request.POST)
if form.is_valid() 
    return redirect ("/")
else:
    ctx = {'form' : form}
    return render(request, "template.htnl,", ctx)
Run Code Online (Sandbox Code Playgroud)

请注意,FormView 将为您处理所有这些;您根本不必定义post或方法。get

  • @DanielRoseman 好的,但是当您在同一页面上有多个表单并且您想用不同的视图处理它们时会发生什么?只有一个“FormView”将处理页面渲染,而其他视图在有效和无效的情况下都必须重定向到“主视图”。 (2认同)