为Django提交表单的更好方法

时间:2011-05-17 07:20:45

标签: django django-forms

这就是我现在正在做的事情:

views.py

def activation_signupcount(request):

    if request.method == 'POST':

        return render_to_response('activation_signupcount.html', 
                                {   'datestart': request.POST['datestart'], 
                                    'dateend': request.POST['dateend'], 
                                    'usersegment': request.POST['usersegment'], 
                                    'segment_form': SegmentForm(request.POST), 
                                    'date_form': DateSelectForm(request.POST)    })
    else:

        return render_to_response('activation_signupcount.html', 
                                {'segment_form': SegmentForm(), 'date_form': DateSelectForm()})

模板

{% extends "base_activation.html" %}

{% block content %}
    <h2>Sign ups</h2>
    <p>Number of users who have registered to the site between the dates entered</p>
{% endblock %}

{% block graph %}
    {% if datestart %}
    <p>This counts the number of <strong>{{ usersegment }}</strong> users who have successfully registered to the site (verified their email)
    who joined between <strong>{{ datestart }}</strong> and <strong>{{ dateend }}</strong></p>
    <img src="./activation_signupcount.png?usersegment={{ usersegment }}&datestart={{ datestart }}&dateend={{ dateend }}" />
    {% endif %}
{% endblock %}

当用户提交SegmentForm和DateSelectForms时,我返回相同的页面。要检查是否应该返回输出(图表),我检查是否存在datestart,如我的模板{% if datestart %}中所示,如果已提交。

这是Djangoic的做法吗?我觉得我应该检查response == 'POST'而不是强制检查变量datestart

谢谢

2 个答案:

答案 0 :(得分:2)

这是提交我见过的表格最奇怪的方式。 :-)首先,您将segment_formdate_form传递给模板,但根本不使用它们。为什么?其次,你没有验证,如果datestart将是'adhbsadfbsrbv'怎么办?还是一些XSS声明?第三,如果POST中没有datestart怎么办?您将获得KeyError

您可以先阅读the docs。你的代码可以像这样重写(甚至更简单的编辑版本):

def activation_signupcount(request):
    return render_to_response('activation_signupcount.html',
                          {'segment_form': SegmentForm(request.POST or None), 'date_form': DateSelectForm(request.POST or None)})

在模板中,您可以访问{{ date_form.cleaned_data.datestart }}等变量,并且在输出网址时不要忘记使用escape过滤器。

答案 1 :(得分:1)

首先,在调试代码时,有几个指针可以帮助您避免麻烦。而不是测试request.method =='POST',检查您附加到表单上的提交按钮(在模板中)的值是否在request.POST字典中。我不确定你是否用一个“提交”按钮提交2个表格,但是如果你这样做,为什么不为它写一个表格呢?

另外,请务必检查表单是否有效。在渲染图形时,这可以为您节省很多麻烦,因为图形代码可以安全地对其接收的数据质量做出某些假设。此外,用户将知道图表不呈现的原因(他将以他的形式收到错误消息)。

您可以在模板或视图中进行验证检查(建议使用后者 - 程序逻辑应驻留在您的视图中)。如果表单有效,他们将获得包含验证数据的“cleaning_data”属性。

在我的脑海中,这是更多Django-ic代码的样子:

def render_view(request):
    if "submit" in request.POST: # Supposing both forms are submitted with one "submit" button
        segment_form = SegmentForm(request.POST)
        dateselect_form = DateSelectForm(request.POST)
    else:
        segment_form = SegmentForm()
        dateselect_form = DateSelectForm()

    return render_to_response('activation_signupcount.html',{'segment_form': segment_form, 'date_form': date_form, 'display_graph': (segment_form.is_valid() and dateselect_form.is_valid())})

然后,在模板中,首先检查表单是否有效(如果两个表单都有效,则'display_graph'变量为True),然后访问其cleaning_data属性以获取所需的值。例如:

{% block graph %}
{% if display_graph %}
    <p>This counts the number of <strong>{{ segment_form.cleaned_data.usersegment }}</strong> users who have successfully registered to the site (verified their email)who joined between <strong>{{ date_form.cleaned_data.datestart }}</strong> and <strong>{{ date_form.cleaned_data.dateend }}</strong></p>
<img src="./activation_signupcount.png?usersegment={{ segment_form.cleaned_data.usersegment }}&datestart={{ date_form.cleaned_data.datestart }}&dateend={{ date_form.cleaned_data.dateend  }}" />
{% endif %}
{% endblock %}