zoukankan      html  css  js  c++  java
  • django book表单验证学习

    django提供了强大的表单验证功能form

    个人认为是把html代码封装到form里面,就像封装models中的数据一样。而且带有强大的验证功能,不需要后台再去写一堆乱七八糟的验证

    具体操作查看django book第七章

    这里记录一下如果修改form中字段的样式

    #coding:utf-8
    from django import forms
    
    class LeaveMessageForm(forms.Form):
        name = forms.CharField(max_length=30, widget=forms.TextInput(attrs={"class": 'input1', 'placeholder':"请输入您的姓名"}))
        email = forms.EmailField(widget=forms.EmailInput(attrs={"class": 'input2', 'placeholder':"请输入您的电子邮箱"}))
        message = forms.CharField(widget=forms.Textarea(attrs={'class':'input2', 'placeholder':"您的留言"}))

    定制widget,然后在attrs里添加其他的css等其他属性

    想form传递参数的时候可以传递多个,例如如果有文件类型的,但是传入request.POST没法获取到,需要多传入一个request.FILES

    form(request.POST)只将request.POST中的值传入表单,如果表单中有文件或者图片的话就无法获取到
    form(request.POST, request.FILES)

    第一个Form类

    Django带有一个form库,称为django.forms,这个库可以处理我们本章所提到的包括HTML表单显示以及验证。 接下来我们来深入了解一下form库,并使用她来重写contact表单应用。

    Django的newforms库

    在Django社区上会经常看到django.newforms这个词语。当人们讨论django.newforms,其实就是我们本章里面介绍的django.forms。

    改名其实有历史原因的。 当Django一次向公众发行时,它有一个复杂难懂的表单系统:django.forms。后来它被完全重写了,新的版本改叫作:django.newforms,这样人们还可以通过名称,使用旧版本。 当Django 1.0发布时,旧版本django.forms就不再使用了,而django.newforms也终于可以名正言顺的叫做:django.forms

    表单框架最主要的用法是,为每一个将要处理的HTML的`` <Form>`` 定义一个Form类。 在这个例子中,我们只有一个`` <Form>`` ,因此我们只需定义一个Form类。 这个类可以存在于任何地方,甚至直接写在`` views.py`` 文件里也行,但是社区的惯例是把Form类都放到一个文件中:forms.py。在存放`` views.py`` 的目录中,创建这个文件,然后输入:

    from django import forms
    
    class ContactForm(forms.Form):
        subject = forms.CharField()
        email = forms.EmailField(required=False)
        message = forms.CharField()

    这看上去简单易懂,并且很像在模块中使用的语法。 表单中的每一个字段(域)作为Form类的属性,被展现成Field类。这里只用到CharFieldEmailField类型。 每一个字段都默认是必填。要使email成为可选项,我们需要指定required=False

    让我们钻研到Python解释器里面看看这个类做了些什么。 它做的第一件事是将自己显示成HTML:

    >>> from contact.forms import ContactForm
    >>> f = ContactForm()
    >>> print f
    <tr><th><label for="id_subject">Subject:</label></th><td><input type="text" name="subject" id="id_subject" /></td></tr>
    <tr><th><label for="id_email">Email:</label></th><td><input type="text" name="email" id="id_email" /></td></tr>
    <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>

    为了便于访问,Django用`` <label>`` 标志,为每一个字段添加了标签。 这个做法使默认行为尽可能合适。

    默认输出按照HTML的<`` table`` >格式,另外有一些其它格式的输出:

    >>> print f.as_ul()
    <li><label for="id_subject">Subject:</label> <input type="text" name="subject" id="id_subject" /></li>
    <li><label for="id_email">Email:</label> <input type="text" name="email" id="id_email" /></li>
    <li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>
    >>> print f.as_p()
    <p><label for="id_subject">Subject:</label> <input type="text" name="subject" id="id_subject" /></p>
    <p><label for="id_email">Email:</label> <input type="text" name="email" id="id_email" /></p>
    <p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>

    请注意,标签<table>、<ul>、<form>的开闭合标记没有包含于输出当中,这样你就可以添加额外的行或者自定义格式。

    这些类方法只是一般情况下用于快捷显示完整表单的方法。 你同样可以用HTML显示个别字段:

    >>> print f['subject']
    <input type="text" name="subject" id="id_subject" />
    >>> print f['message']
    <input type="text" name="message" id="id_message" />

    Form对象做的第二件事是校验数据。 为了校验数据,我们创建一个新的对Form象,并且传入一个与定义匹配的字典类型数据:

    >>> f = ContactForm({'subject': 'Hello', 'email': 'adrian@example.com', 'message': 'Nice site!'})

    一旦你对一个Form实体赋值,你就得到了一个绑定form:

    >>> f.is_bound
    True

    调用任何绑定form的is_valid()方法,就可以知道它的数据是否合法。 我们已经为每个字段传入了值,因此整个Form是合法的:

    >>> f.is_valid()
    True

    如果我们不传入email值,它依然是合法的。因为我们指定这个字段的属性required=False

    >>> f = ContactForm({'subject': 'Hello', 'message': 'Nice site!'})
    >>> f.is_valid()
    True

    但是,如果留空subjectmessage,整个Form就不再合法了:

    >>> f = ContactForm({'subject': 'Hello'})
    >>> f.is_valid()
    False
    >>> f = ContactForm({'subject': 'Hello', 'message': ''})
    >>> f.is_valid()
    False

    你可以逐一查看每个字段的出错消息:

    >>> f = ContactForm({'subject': 'Hello', 'message': ''})
    >>> f['message'].errors
    [u'This field is required.']
    >>> f['subject'].errors
    []
    >>> f['email'].errors
    []

    每一个邦定Form实体都有一个errors属性,它为你提供了一个字段与错误消息相映射的字典表。

    >>> f = ContactForm({'subject': 'Hello', 'message': ''})
    >>> f.errors
    {'message': [u'This field is required.']}

    最终,如果一个Form实体的数据是合法的,它就会有一个可用的cleaned_data属性。 这是一个包含干净的提交数据的字典。 Django的form框架不但校验数据,它还会把它们转换成相应的Python类型数据,这叫做清理数据。

    >>> f = ContactForm({subject': Hello, email: adrian@example.com, message: Nice site!})
    >>> f.is_valid()
    True
    >>> f.cleaned_data
    {message': uNice site!, email: uadrian@example.com, subject: uHello}

    我们的contact form只涉及字符串类型,它们会被清理成Unicode对象。如果我们使用整数型或日期型,form框架会确保方法使用合适的Python整数型或datetime.date型对象。

    在视图中使用Form对象

    在学习了关于Form类的基本知识后,你会看到我们如何把它用到视图中,取代contact()代码中不整齐的部分。 一下示例说明了我们如何用forms框架重写contact()

    # views.py
    
    from django.shortcuts import render_to_response
    from mysite.contact.forms import ContactForm
    
    def contact(request):
        if request.method == 'POST':
            form = ContactForm(request.POST)
            if form.is_valid():
                cd = form.cleaned_data
                send_mail(
                    cd['subject'],
                    cd['message'],
                    cd.get('email', 'noreply@example.com'),
                    ['siteowner@example.com'],
                )
                return HttpResponseRedirect('/contact/thanks/')
        else:
            form = ContactForm()
        return render_to_response('contact_form.html', {'form': form})
    # contact_form.html
    
    <html>
    <head>
        <title>Contact us</title>
    </head>
    <body>
        <h1>Contact us</h1>
    
        {% if form.errors %}
            <p style="color: red;">
                Please correct the error{{ form.errors|pluralize }} below.
            </p>
        {% endif %}
    
        <form action="" method="post">
            <table>
                {{ form.as_table }}
            </table>
            <input type="submit" value="Submit">
        </form>
    </body>
    </html>

    看看,我们能移除这么多不整齐的代码! Django的forms框架处理HTML显示、数据校验、数据清理和表单错误重现。

    尝试在本地运行。 装载表单,先留空所有字段提交空表单;继而填写一个错误的邮箱地址再尝试提交表单;最后再用正确数据提交表单。 (根据服务器的设置,当send_mail()被调用时,你将得到一个错误提示。而这是另一个问题。)

    改变字段显示

    你可能首先注意到:当你在本地显示这个表单的时,message字段被显示成`` input type=”text”`` ,而它应该被显示成<`` textarea`` >。我们可以通过设置* widget* 来修改它:

    from django import forms
    
    class ContactForm(forms.Form):
        subject = forms.CharField()
        email = forms.EmailField(required=False)
        message = forms.CharField(**widget=forms.Textarea** )

    forms框架把每一个字段的显示逻辑分离到一组部件(widget)中。 每一个字段类型都拥有一个默认的部件,我们也可以容易地替换掉默认的部件,或者提供一个自定义的部件。

    考虑一下Field类表现* 校验逻辑* ,而部件表现* 显示逻辑* 。

    设置最大长度

    一个最经常使用的校验要求是检查字段长度。 另外,我们应该改进ContactForm,使subject限制在100个字符以内。 为此,仅需为CharField提供max_length参数,像这样:

    from django import forms
    
    class ContactForm(forms.Form):
        subject = forms.CharField(**max_length=100** )
        email = forms.EmailField(required=False)
        message = forms.CharField(widget=forms.Textarea)

    选项min_length参数同样可用。

    设置初始值

    让我们再改进一下这个表单:为字subject段添加* 初始值* : "I love your site!" (一点建议,但没坏处。)为此,我们可以在创建Form实体时,使用initial参数:

    def contact(request):
        if request.method == 'POST':
            form = ContactForm(request.POST)
            if form.is_valid():
                cd = form.cleaned_data
                send_mail(
                    cd['subject'],
                    cd['message'],
                    cd.get('email', `'noreply@example.com`_'),
                    [`'siteowner@example.com`_'],
                )
                return HttpResponseRedirect('/contact/thanks/')
        else:
            form = ContactForm(
                **initial={'subject': 'I love your site!'}**
            )
        return render_to_response('contact_form.html', {'form': form})

    现在,subject字段将被那个句子填充。

    请注意,传入* 初始值* 数据和传入数据以* 绑定* 表单是有区别的。 最大的区别是,如果仅传入* 初始值* 数据,表单是unbound的,那意味着它没有错误消息。

    自定义校验规则

    假设我们已经发布了反馈页面了,email已经开始源源不断地涌入了。 这里有一个问题: 一些提交的消息只有一两个字,我们无法得知详细的信息。 所以我们决定增加一条新的校验: 来点专业精神,最起码写四个字,拜托。

    我们有很多的方法把我们的自定义校验挂在Django的form上。 如果我们的规则会被一次又一次的使用,我们可以创建一个自定义的字段类型。 大多数的自定义校验都是一次性的,可以直接绑定到form类.

    我们希望`` message`` 字段有一个额外的校验,我们增加一个`` clean_message()`` 方法到`` Form`` 类:

    from django import forms
    
    class ContactForm(forms.Form):
        subject = forms.CharField(max_length=100)
        email = forms.EmailField(required=False)
        message = forms.CharField(widget=forms.Textarea)
    
        def clean_message(self):
            message = self.cleaned_data['message']
            num_words = len(message.split())
            if num_words < 4:
                raise forms.ValidationError("Not enough words!")
            return message

    Django的form系统自动寻找匹配的函数方法,该方法名称以clean_开头,并以字段名称结束。 如果有这样的方法,它将在校验时被调用。

    特别地,clean_message()方法将在指定字段的默认校验逻辑执行* 之后* 被调用。(本例中,在必填CharField这个校验逻辑之后。)因为字段数据已经被部分处理,所以它被从self.cleaned_data中提取出来了。同样,我们不必担心数据是否为空,因为它已经被校验过了。

    我们简单地使用了len()和split()的组合来计算单词的数量。 如果用户输入字数不足,我们抛出一个forms.ValidationError型异常。这个异常的描述会被作为错误列表中的一项显示给用户。

    在函数的末尾显式地返回字段的值非常重要。 我们可以在我们自定义的校验方法中修改它的值(或者把它转换成另一种Python类型)。 如果我们忘记了这一步,None值就会返回,原始的数据就丢失掉了。

    指定标签

    HTML表单中自动生成的标签默认是按照规则生成的:用空格代替下划线,首字母大写。如email的标签是"Email" 。(好像在哪听到过? 是的,同样的逻辑被用于模块(model)中字段的verbose_name值。 我们在第五章谈到过。)

    像在模块中做过的那样,我们同样可以自定义字段的标签。 仅需使用label,像这样:

    class ContactForm(forms.Form):
        subject = forms.CharField(max_length=100)
        email = forms.EmailField(required=False, **label='Your e-mail address'** )
        message = forms.CharField(widget=forms.Textarea)

    定制Form设计

    在上面的`` contact_form.html`` 模板中我们使用`` {{form.as_table}}`` 显示表单,不过我们可以使用其他更精确控制表单显示的方法。

    修改form的显示的最快捷的方式是使用CSS。 尤其是错误列表,可以增强视觉效果。自动生成的错误列表精确的使用`` <ul class=”errorlist”>``,这样,我们就可以针对它们使用CSS。 下面的CSS让错误更加醒目了:

    <style type="text/css">
        ul.errorlist {
            margin: 0;
            padding: 0;
        }
        .errorlist li {
            background-color: red;
            color: white;
            display: block;
            font-size: 10px;
            margin: 0 0 3px;
            padding: 4px 5px;
        }
    </style>

    虽然,自动生成HTML是很方便的,但是在某些时候,你会想覆盖默认的显示。 {{form.as_table}}和其它的方法在开发的时候是一个快捷的方式,form的显示方式也可以在form中被方便地重写。

    每一个字段部件(<input type=”text”>, <select>, <textarea>, 或者类似)都可以通过访问{{form.字段名}}进行单独的渲染。

    <html>
    <head>
        <title>Contact us</title>
    </head>
    <body>
        <h1>Contact us</h1>
    
        {% if form.errors %}
            <p style="color: red;">
                Please correct the error{{ form.errors|pluralize }} below.
            </p>
        {% endif %}
    
        <form action="" method="post">
            <div class="field">
                {{ form.subject.errors }}
                <label for="id_subject">Subject:</label>
                {{ form.subject }}
            </div>
            <div class="field">
                {{ form.email.errors }}
                <label for="id_email">Your e-mail address:</label>
                {{ form.email }}
            </div>
            <div class="field">
                {{ form.message.errors }}
                <label for="id_message">Message:</label>
                {{ form.message }}
            </div>
            <input type="submit" value="Submit">
        </form>
    </body>
    </html>

    {{ form.message.errors }} 会在 <ul class="errorlist"> 里面显示,如果字段是合法的,或者form没有被绑定,就显示一个空字符串。 我们还可以把 form.message.errors 当作一个布尔值或者当它是list在上面做迭代, 例如:

    <div class="field{% if form.message.errors %} errors{% endif %}">
        {% if form.message.errors %}
            <ul>
            {% for error in form.message.errors %}
                <li><strong>{{ error }}</strong></li>
            {% endfor %}
            </ul>
        {% endif %}
        <label for="id_message">Message:</label>
        {{ form.message }}
    </div>

    在校验失败的情况下, 这段代码会在包含错误字段的div的class属性中增加一个”errors”,在一个有序列表中显示错误信息。

    摘自django book2.0中文版第七章表单

  • 相关阅读:
    反射
    IDEA配置数据库
    配置idea的maven镜像为aliyun
    蓝桥---芯片测试(思维)
    汉诺塔(思维、DP思想)
    立方数(质因子、优化)
    碎碎念(DP)
    牛牛战队的比赛地(三分)
    子段乘积(尺取、逆元)
    子段异或(位运算)
  • 原文地址:https://www.cnblogs.com/lgh344902118/p/6952261.html
Copyright © 2011-2022 走看看