Django:发布重定向后获取表单上的验证错误反馈

时间:2019-02-14 17:12:05

标签: 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('/')

我的模板真的很基础(我喜欢这个简单性):

<p>
  <form action="" method="post">
    {% csrf_token %}
    <table>
    {{ form.as_table }}
    </table>
    <input type="submit" value="Submit">
  </form>
</p>

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

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

form.html

我没有包括所有Python代码来完成这项工作-但您明白了。  这感觉更优雅,因为我没有在会话中放入HTML斑点,但是错误以不同于常规Django形式的方式显示。而且,如果我使用的是松脆的表单,那么所有松脆的UI优点都将无法发挥作用。

我什至考虑过将{% if errors %} {% for error in errors %} <p style="color:red">Error in {{ error.label }}: {{ error.message }}</p> {% endfor %} {% endif %} 代码中的错误通过会话传递给post(),然后将它们插入{{1}中的get()对象中}放在form之前-也会感觉更优雅。如果我觉得无聊,我可能会尝试深入研究表单结构并实现它。

我简直不敢相信Django具有如此强大的内置魔法-我不能只在get()代码中说出render()之类的东西。

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

1 个答案:

答案 0 :(得分:0)

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

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

注意,FormView将为您处理所有这些;您完全不必定义postget方法。