zoukankan      html  css  js  c++  java
  • django-forms

    HTML form是交互网页的支柱。下面来学习一下有关使用Django处理用户提交的表单数据,验证等功能。

    我们将讨论HttpRequest和Form对象。
    • request中包含的信息
    在views.py中的每一个用于显示页面的函数都需要以request作为第一个函数参数。request包含了一些有用
    的信息,如:
    request.path               除去了域名和端口的访问路径,
    request.get_host       域名+端口信息
    request.get_full_path()   所有路径,包含传递的参数
    requets.is_secure()     是否使用https进行链接
    还有一个特别的属性request.META,它是一个dict类型,包含了所有HTTP header信息,不过也要根据用户
    的实际环境来决定。如
    HTTP_REFERER
    HTTP_USER_AGENT   用户使用的浏览器信息
    REMOTE_ADDR     用户的IP,如果使用代理,也可以显示出来
    (有很多属性,只是截图了一些)
      
    并不是每一个用户提交的头信息都相同,所以在读取的时候,要考虑一些异常情况,比如取不到相应的值的情况。
    可以使用try...except,也可以使用dict.get(key, default)中默认返回为预设值的方法。
    def ua_display_good1(request):
        try:
            ua = request.META['HTTP_USER_AGENT']
        except KeyError:
            ua = 'unknown'
        return HttpResponse("Your browser is %s" % ua)
     
    def ua_display_good2(request):
        ua = request.META.get('HTTP_USER_AGENT', 'unknown')
        return HttpResponse("Your browser is %s" % ua)
     
    除了以上的这些元数据的信息,HttpRequest对象还包括两个属性包括了用户提交的数据:
    request.GET和request.POST。它们都是dictionary-like对象。意思就是说可以像dict那样
    操作,但不是dict,还有一些dict没有的操作。
     
    下面构造一个用于用户搜索的简单form例子。
    #template/search_form.html
    <form action="/search/" method="get">
        <input type="text" name="q">
        <input type="submit" value="Search">
    </form>
    #template/search_results.html
    <p>Your searched for '{{ query }}'
    {% if books %}
        {% for book in books %}
            <li>{{ book.title }}</li>
        {% endfor %}
    {% else %}
        <p>No books found.
    {% endif %}
    # urls.py
    from django.conf.urls import patterns, include, url
    from books.views import hello, search_form, search
    urlpatterns = patterns('',
        url(r'^search-form/$', search_form),
        url(r'^search/$', search),                     
    )
    #views.py
    from django.http import HttpResponse
    from django.shortcuts import render_to_response
    from books.models import Book

    def search_form(request):
        return render_to_response('search_form.html')

    def search(request):
        if 'q' in request.GET:#GET是一个dict,使用文本框的name作为key
        #在这里需要做一个判断,是否存在提交数据,以免报错
            q = request.GET['q']
            #使用lookup后缀,意思为书名不区分大小写,包含q就可以
            books = Book.objects.filter(title__icontains=q)
            return render_to_response('search_results.html', {'books' : books, 'query':q})
        else:
            message = 'You submitted an empty form.'
            #只是简单的返回一个response对象,因为没有使用模块,所以也不用渲染数据Context
            return HttpResponse(message)
     
    还有一点,form中的action属性如果为空的,代表提交数据到当前页面。    
     
    关于表单验证
    可以在server端进行,有时会加重server负担,也可以使用Javascript在client端进行。有一点需要注意的是,
    即使你使用了javascript在client进行了验证,还是需要在server端对用户提交的数据进行审查,比如有些人
    会在浏览器中禁用javascript,也有些人会来搞注入攻击。总之,不能相信用户提交的提交,进行防御性编码。
     
    关于使用重定向
    你应当总是在一个成功处理POST请求之后进行redirect,这样可以避免用户多次点击提交按钮带来的二次请求
    问题,有时会造成不好的后果,如向数据库插入重复记录等。
    from django.http import HttpResponseRedirect
    return HttpResponseRedirect('/success/')
    • 使用Django的form system来简化表单工作
    在app文件夹下创建forms.py,其实在哪里创建都可以:
    from django import forms
     
    class ContactForm(forms.Form):
        subject = forms.CharField()
        email = forms.EmailField(required=False)
        message = forms.CharField()
    form的定义和model类的定义很像。我们可以使用python manage.py shell来查看form类的信息。
     
    可以看到打印出来的f的信息其实是网页格式的。
    也可以改变默认表格的格式。
     
    这里的<table>,<ul>都没有包含在输出里,所以可以自由地添加行等。
    除了打印出整个form的HTML内容,还可以打印出局的字段的内容。
     
     
    还可以使用form类进行验证,使用dict对form类进行初始化。
    >>> f = ContactForm({'subject': 'Hello', 'email': 'adrian@example.com', 'message': 'Nice'})
    >>> f.is_bound #是否绑定表单类
    True
    >>> f.is_valid() #数据内容是否合法
    True
    当数据全部合法时,可以使用clean_data这个属性,用来得到经过'clean'格式化的数据,会所提交过
    来的数据转化成合适的Python的类型。
     
    如何在view中使用form类
    # views.py

    from django.shortcuts import render_to_response
    from mysite.contact.forms import ContactForm

    def contact(request):
        #可以不写,因为python中if中定义的变量,也可以在整个函数中可见    
        form = None 
        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/')#需要在urls.py中配置路径
        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;">
                {# pulralize 是filter,用来判断是否为添加's'来表示单词的复数形式#}
                Please correct the error{{ form.errors|pluralize }} below.
            </p>
        {% endif %}

        <form action="" method="post">
            <table>
                {# 可以使用as_ul, as_p来改变格式 #}
                {{ form.as_table }}
            </table>
            <input type="submit" value="Submit">
        </form>
    </body>
    </html>
     
    在构造form的时候,还可以改变字段的构造参数
    class ContactForm(forms.Form):
        subject = forms.CharField(max_length=100)
        email = forms.EmailField(required=False)
        message = forms.CharField(widget=forms.Textarea)
    还可以给form类添加默认值
    form = ContactForm(
                initial={'subject': 'I love your site!'}
            )
     
    给form类自定义验证规则,如果想要重用验证机制,可以单独创建新的字段类,重新写它的验证方法。
    一般的可以直接在form类加入clean_字段名的方法,Django会自动查找以clean_开头的函数名,并会在
    验证该字段的时候,运行这个函数。
    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
    在自定义的验证函数中,我们必须显示的返回字段名的内容,否则会带来表单数据丢失。
     
    可以改变字段的label显示的名称
    email = forms.EmailField(required=False, label='Your e-mail address')
  • 相关阅读:
    非网管交换机和网管交换机的区别
    百兆工业交换机与千兆工业交换机如何计算码率?
    光纤收发器的测试内容介绍
    使用expect在script中切换到root用户(精华)
    彻底解决ssh.invoke_shell() 返回的中文问题
    Python3之paramiko模块
    linux expect详解
    Apache HTTP Server 虚拟主机配置
    Apache 配置详解
    apache 基本配置
  • 原文地址:https://www.cnblogs.com/muzinan110/p/5019590.html
Copyright © 2011-2022 走看看