简体   繁体   English

Django:发布重定向后,在表单上提供验证错误反馈

[英]Django: Giving validation error feedback on a form after a post redirect get

I have a good bit of experience in non-Django web development, but I am struggling to find a good practice for handling what to do when the user enters invalid data in their form and I want to re-display the form with their submitted data and the form errors displayed as well. 我在非Django Web开发方面有丰富的经验,但是我在努力寻找一种很好的做法来处理当用户在表单中输入无效数据并且我想用提交的数据重新显示表单时如何处理并显示表单错误。 I have a simple form with three fields and this is how I finally made it work. 我有一个包含三个字段的简单表单,这就是我最终使它工作的方式。

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

My template is really basic (I like this simplicity): 我的模板真的很基础(我喜欢这种简单性):

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

Now this approach kind of weirds me out because I am sending the entire rendered HTML page through the session from the post() to the get() . 现在,这种方法让我感到很奇怪,因为我正在通过会话将整个呈现的HTML页面从post()发送到get() But I can't send the form with the errors in place through the session back to the the get() (that would be prettier) because it won't serialize - you get "Object of type 'BasicForm' is not JSON serializable". 但是我无法将通过会话将有错误的form发送回get() (那会更漂亮),因为它不会序列化-您会收到“ BasicForm'类型的对象不可JSON序列化” 。

I have done this a different way where I extract the errors form the form object into a list and then pass my own list of errors from the post() to the redirected get() and then alter form.html to display errors. 我采用了另一种方式,将错误从form对象提取到list ,然后将自己的错误列表从post()传递到重定向的get() ,然后更改form.html以显示错误。

{% if errors %}
    {% for error in errors %}
    <p style="color:red">Error in {{ error.label }}: {{ error.message }}</p>
    {% endfor %}
{% endif %}

I have not included all the Python code to make this work - but you get the idea. 我没有包括所有的Python代码来完成这项工作-但您明白了。 This feels more elegant because I am not putting a blob of HTML into the session, but then the errors display in a way other than the normal Django forms way. 这感觉更优雅,因为我没有在会话中放入HTML斑点,但是错误以不同于常规Django形式的方式显示。 And if I were using crispy forms - then all that crispy UI goodness would not come into play. 而且,如果我使用的是松脆的表单,那么所有松脆的UI优点都不会发挥作用。

I even thought about pulling out the errors in the post() code and passing them to the get() through the session and then inserting them into the form object in the get() prior to render() - that would feel more elegant too. 我什至考虑过要删除post()代码中的错误,并通过会话将它们传递给get() ,然后将它们插入到render()之前的get()form对象中-这样也会感觉更优雅。 If I get bored I might try to dig through the forms structure and implement this as well. 如果我感到无聊,我可能会尝试深入研究表单结构并实现它。

I just cannot believe that with Django having so mush awesome built-in magic - that I can't just say something like return form.post_redirect_get() in the not form.is_valid code. 我简直不敢相信Django具有如此强大的内置魔术-我不能只用not form.is_valid代码说诸如return form.post_redirect_get()类的东西。

I want something that is a replicable pattern that is easily explained and used the Django UI elements as much as possible. 我想要一种易于复制的模式,可以轻松地解释并尽可能多地使用Django UI元素。

You're misunderstanding. 你误会了 You're only supposed to redirect after a successful post. 成功发布后,您只应重​​定向。 On a post that fails validation, you don't redirect at all, you redisplay the invalid form - whichwill show the validation errors. 在验证失败的帖子上,您根本不会重定向,而是重新显示无效的表单-这将显示验证错误。

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

Note, a FormView will handle all this for you; 注意,FormView将为您处理所有这些; you shouldn't have to define post or get methods at all. 您根本不需要定义postget方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM