Form验证

django中的Form一般有两种功能:

  • 输入html-----------不能你自己写一些标签,而帮你自动生成
  • 验证用户输入-------将用户验证信息保存起来,可以传到前段
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django.shortcuts import render,HttpResponse
from app.froms import Form1
from app import models
def form1(request):
    if request.method == 'POST':
        # request.POST.get('user',None)
        # request.POST.get('pwd',None)
        f1 = Form1(request.POST)  #request.POST用于获取数据,这里的f1和下面的f2不一样,这里有参数可以获取错误信息
        if f1.is_valid():
            print(f1.cleaned_data)#验证成功,获取用户信息
        else:
            print(f1.errors)  # 验证错误,获取错误信息
            return render(request,'account/from.html',{'f':f1})
    else:
        f2 = Form1()  #这里的f2不能获取信息
        return render(request,'account/from.html',{'f':f2})
    return HttpResponse('OK')
View
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/from1/" method="post">
    <div>
        {{ f.user }}
        {% if f.errors.user.0 %}
        <span>{{ f.errors.user.0 }}</span>
        {% endif %}
    </div>
    <div>
        {{ f.pwd }}
        {% if f.errors.pwd.0 %}
        <span>{{ f.errors.pwd.0 }}</span>
        {% endif %}
    </div>
    <div>
        {{ f.email }}
        {% if f.errors.email.0 %}
        <span>{{ f.errors.email.0 }}</span>
        {% endif %}
    </div>
    <div>
        <input type="submit" value="提交">
    </div>
</form>
</body>
</html>
form.html
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django import forms

class Form1(forms.Form):
    user = forms.CharField(
        widget=forms.TextInput(attrs={'class':'c1'}),
        error_messages={'required':'用户名不能为空'},)

    pwd = forms.CharField(max_length=4,min_length=2)
    email = forms.EmailField(error_messages={'required':'邮箱不能为空','invalid':'邮箱格式错误'})
froms

-----------------------------------总结:-----------------------------------------

1、<form action="/from1/" method="post">中url必须要包括在/xxx/中间,因为,无论你在路由中有没有写最后的/在跳转的时候,浏览器都会为你自动加上,所以你必须加上,不然会报错

 

2、input标签你自己可以在html中创建,也可以利用djanjo创建,利用djanjo创建的好处是,当你在input标签中写入数据后,提交刷新页面的时候,数据还存在,因为在你写的f1 = Form1(request.POST)中已经存在你所输入的数据

 

3、在render(requset,{})中传参数的时候,既可以用local()进行传递,又可以用字典进行传递

 

4、后台获取数据的时候,不能通过索引进行取值,例f['user']会报错,应该通过 . 进行获取值

 

5、request.method == 'POST' 其中的POST,必须大写,不然会报错

一、forms.CharField()中参数总结

required=False   ---------------------------------------------------------------------------------------------------------------可以为空,默认为Ture不能为空

max_length=10       ---------------------------------------------------------------------------------------------------------------最多10个字符

mix_length=10        ---------------------------------------------------------------------------------------------------------------最少10个字符

error_messages={'required':'用户名不能为空','min_length':'标题最少为5个字符','max_length':'标题最多为20个字符'}----自定义错误信息

widget=forms.TextInput()--------------------------------------------------------------------------------------------------------默认是input标签

widget=forms.Textarea()----------------------------------------------------------------------------------------------------------文本标签

...........

widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': '邮箱'}),------------------------------------为标签设置class属性以及显示

==============================================================================================

下拉框,参数choices=xxx是固定格式,参数a的形式必须写成下面这种形式,当我们往数据库中添加数据的时候,在不从新启动服务的情况下,下拉框中的数据不会更新,因为类下的静态字段只创建一次,创建对象只执行__init__方法,所以必须在创建对象执行__init__方法的时候再一次执行一下静态字段就可以达到更新的目的

a = (

  (6,'乒乓球'),

  (1,'足球'),

  (2,'篮球'),

  (3,'手球'),

)

forms.CharField( widget=forms.Select(choices=a) )

自定制验证规则:

自己可以自定义验证规则,加到里面

from django.core.exceptions import ValidationError
from django import forms
import re
def mobile_validate(value):
    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('手机号码格式错误')
pwd = forms.CharField(validators=[mobile_validate, ],
                    
                    error_messages={'required': u'手机不能为空'},
                    widget=forms.TextInput(attrs={'class': "form-control",'placeholder': u'手机号码'}))
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
from django import forms
from django.core.exceptions import ValidationError


def mobile_validate(value):
    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('手机号码格式错误')


class PublishForm(forms.Form):

    user_type_choice = (
        (0, u'普通用户'),
        (1, u'高级用户'),
    )

    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
                                                                  attrs={'class': "form-control"}))

    title = forms.CharField(max_length=20,
                            min_length=5,
                            error_messages={'required': u'标题不能为空',
                                            'min_length': u'标题最少为5个字符',
                                            'max_length': u'标题最多为20个字符'},
                            widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'标题5-20个字符'}))

    memo = forms.CharField(required=False,
                           max_length=256,
                           widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'详细描述', 'rows': 3}))

    phone = forms.CharField(validators=[mobile_validate, ],
                            error_messages={'required': u'手机不能为空'},
                            widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'手机号码'}))

    email = forms.EmailField(required=False,
                            error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},
                            widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))
Form

Cookie

1、设置及获取Cookie:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django.shortcuts import render,HttpResponse

def form1(request):
    print(request.COOKIES)
    print(request.COOKIES['k9'])  #如果没有的话会报错
    print(request.get_signed_cookie('k3',salt='alex',default=None))  #获取的时候也得加salt

    rep = HttpResponse('GHHG')

    rep.set_cookie('k1',1213)
    rep.set_signed_cookie('k3',456,salt='alex',)
    return rep
request.COOKIES['key']

request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

    参数:

        default: 默认值

           salt: 加密盐

        max_age: 后台控制过期时间

2、设置Cookie:

rep = HttpResponse(...) 或 rep = render(request, ...)

rep.set_cookie(key,value,...)

rep.set_signed_cookie(key,value,salt='加密盐',...)

    参数:

        key,              键

        value='',         值

        max_age=None,     超时时间

        expires=None,     超时时间(IE requires expires, so set it if hasn't been already.)

        path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问

        domain=None,      Cookie生效的域名

        secure=False,     https传输

        httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

max_age=None,    后面直接写时间就可以了

expires=None ,   必须写获取当前时间,再设置以当前时间为准,多长时间后失效    expires= time.time() + 10

由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。

<script src='/static/js/jquery.cookie.js'></script>

$.cookie("list_pager_num", 30,{ path: '/' });

 Session

Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

  • 数据库(默认)
  • 缓存
  • 文件
  • 缓存+数据库
  • 加密cookie

1、数据库Session

Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。

 

a. 配置 settings.py

 

    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)

     

    SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)

    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)

    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)

    SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)

    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)

    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)

    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)

    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)

 

 

 

b. 使用

 

    def index(request):

        # 获取、设置、删除Session中数据

        request.session['k1']

        request.session.get('k1',None)

        request.session['k1'] = 123

        request.session.setdefault('k1',123) # 存在则不设置

        del request.session['k1']

 

        # 所有 键、值、键值对

        request.session.keys()

        request.session.values()

        request.session.items()

        request.session.iterkeys()

        request.session.itervalues()

        request.session.iteritems()

 

 

        # 用户session的随机字符串

        request.session.session_key

 

        # 将所有Session失效日期小于当前日期的数据删除

        request.session.clear_expired()

 

        # 检查 用户session的随机字符串 在数据库中是否

        request.session.exists("session_key")

 

        # 删除当前用户的所有Session数据

        request.session.delete("session_key")

 

        ...
数据库Session

2、缓存Session

a. 配置 settings.py

 

    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎

    SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置

 

 

    SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串

    SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路径

    SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名

    SESSION_COOKIE_SECURE = False                             # 是否Https传输cookie

    SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http传输

    SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)

    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期

    SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存

 

 

 

b. 使用

 

    同上
缓存Session

3、文件Session

a. 配置 settings.py

 

    SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎

    SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T 

 

 

    SESSION_COOKIE_NAME = "sessionid"                          # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串

    SESSION_COOKIE_PATH = "/"                                  # Session的cookie保存的路径

    SESSION_COOKIE_DOMAIN = None                                # Session的cookie保存的域名

    SESSION_COOKIE_SECURE = False                               # 是否Https传输cookie

    SESSION_COOKIE_HTTPONLY = True                              # 是否Session的cookie只支持http传输

    SESSION_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)

    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否关闭浏览器使得Session过期

    SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次请求都保存Session,默认修改之后才保存

 

b. 使用

 

    同上
文件Session

4、缓存+数据库Session

数据库用于做持久化,缓存用于提高效率


a. 配置 settings.py


    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

 
b. 使用


    同上
缓存+数据库Session

5、加密cookie Session

a. 配置 settings.py

    
    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎

 
b. 使用

    同上
Session用户验证

扩展:Session用户验证(装饰器)

    def login(func):
        def wrap(request, *args, **kwargs):
            # 如果未登陆,跳转到指定页面
            if request.session['is_login']:
                return redirect('http://www.baidu.com')
            return func(request, *args, **kwargs)
        return wrap
    return  HttpResponse('GHHG')

跨站请求伪造(csrf)

一、简介

如果在配置中加入 'django.middleware.csrf.CsrfViewMiddleware',  post请求就会开启验证,如果为验证通过,post请求不会通过,如果想通过验证,就在html的body部分加入

{% csrf_token %}--------------->第一次get请求的时候,会随机生成一个具有验证功能的字符串,当我们通过post方式进行请求的时候,就会通过验证

 

django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

全局:

  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

  • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
  • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

二、应用

1、普通表单

veiw中设置返回值:

  return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))  

     或者
     return render(request, 'xxx.html', data)
html中设置Token:   {% csrf_token %} 

2、Ajax

对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。

view.py

from django.template.context import RequestContext

# Create your views here.

def test(request):

    if request.method == 'POST':

        print request.POST

        return HttpResponse('ok')

    return  render_to_response('app01/test.html',context_instance=RequestContext(request))

text.html

<!DOCTYPE html>

<html>

<head lang="en">

    <meta charset="UTF-8">

    <title></title>

</head>

<body>

    {% csrf_token %}

    <input type="button" onclick="Do();"  value="Do it"/>

    <script src="/static/plugin/jquery/jquery-1.8.0.js"></script>

    <script src="/static/plugin/jquery/jquery.cookie.js"></script>

    <script type="text/javascript">

        var csrftoken = $.cookie('csrftoken');

  

        function csrfSafeMethod(method) {

            // these HTTP methods do not require CSRF protection

            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));

        }

        $.ajaxSetup({

            beforeSend: function(xhr, settings) {

                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {

                    xhr.setRequestHeader("X-CSRFToken", csrftoken);

                }

            }

        });

        function Do(){

            $.ajax({

                url:"/app01/test/",

                data:{id:1},

                type:'POST',

                success:function(data){

                    console.log(data);

                }

            });
        }

    </script>

</body>

</html>

 

posted on 2016-08-25 19:00  23云恋49枫  阅读(360)  评论(0编辑  收藏  举报