22.django:session_csrf_中间件_缓存_信号_form

一、session使用:                                                                                                                       

   1.原理:session是服务器端通过生成一个大的字典存储每个用户相关的session信息,在生成session信息的时候,服务器端会在客户端写入一条字符串,同时在服务器端也生成一个同样字符串为key的字典,字典内容存储用户相关的登陆信息。

   2.相关脚本:   

=====1.login.html=====
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action = "/day22/login/" method="post">
        <input type="text" name="username" placeholder="用户名">
        <input type="password" name="password" placeholder="密码">
        <input type="submit" value="提交">
    </form>

</body>
</html>

=======2.index.html=======
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>welcome to :{{ username }}</h1>
</body>
</html>

====3.views.py=======
from django.shortcuts import render,redirect

# Create your views here.


def login(request):
    if request.method =="GET":
        return render(request,"day22/login.html")
    elif request.method == "POST":
        user = request.POST.get("username")
        pwd = request.POST.get("password")

        if user== 'root' and pwd=='123':
            request.session['username'] = user
            request.session['is_login'] = True

            return redirect('/day22/index/')
        else:
            return redirect("/day22/login/")
    else:
        return render(request, "day22/login.html")


def index(request):
    if request.session['is_login']:
        return render(request,'day22/index.html',{'username':request.session['username']})
    else:
        return redirect('/day22/login/')


========4.urls.py========
from django.conf.urls import url,include
from django.contrib import admin
from day22 import views

urlpatterns = [
     url(r'^login/$', views.login),
     url(r'^index/$', views.index),
]

 3.request.session内容的添、删、改、查

1.获取session值
request.session['username']   #获取username值
request.session.get('username',None)  获取username的值,如果没有设置username的值为None

2.给session赋值
request.session['username']= zhangsan  #设置session中username的值为zhangsan
request.session.setdefault('username',zhangsan) #如果username中存在值,则不进行设置,如果不存在设置为zhangsan

3.删除session中的值
del request.session['username']    #删除session中的username
request.session.delete("session_key")   #删除某个session_key的session信息
request.session.clear() == request.session.delete(request.session.session_key)   #注销时用


4.session中键、值对的获取
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()

5.用户session的随机字符串
request.session.session_key

6.将所有session失效日期小于当前日期的数据删除
request.session.clear_expired()

7.检查用户session的随机字符串在数据库中是否存在
request.session.exists("session_key")

8.request.session.set_expiry(value)
     * 如果value是个整数,session会在value秒后失效
     * 如果value是个datatime或timedelta,session就会在这个时间后失效。
     *如果value是0,用户关闭浏览器session就会失效。
     *如果value是None,session会依赖全局session失效策略

4.requist.session超时时间设定,默认session超时时间为两周

1.session全局参数设定    settings.py中的配置
SESSION_COOKIE_NAME == "sessionid"   #Session的cookie保存在浏览器上的key
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,默认为否
2.相关脚本
========index.html======
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>welcome to :{{ username }}</h1>
    <a href="/day22/logout/">注销</a>
</body>
</html>
======login.html=====
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action = "/day22/login/" method="post">
        <input type="text" name="username" placeholder="用户名" />
        <input type="password" name="password" placeholder="密码" />
        <input type="checkbox" value="1" name="rmb" /> 超时时间10S
        <input type="submit" value="提交">
    </form>

</body>
</html>

====views.py======
from django.shortcuts import render,redirect

# Create your views here.


def login(request):
    if request.method =="GET":
        return render(request,"day22/login.html")
    elif request.method == "POST":
        user = request.POST.get("username")
        pwd = request.POST.get("password")

        if user== 'root' and pwd=='123':
            request.session['username'] = user
            request.session['is_login'] = True
            if request.POST.get('rmb',None) == '1':
                request.session.set_expiry(10)

            return redirect('/day22/index/')
        else:
            return redirect("/day22/login/")
    else:
        return render(request, "day22/login.html")


def index(request):
    if request.session.get('is_login',None):
        return render(request,'day22/index.html',{'username':request.session['username']})
    else:
        return redirect('/day22/login/')

def logout(request):
    request.session.clear()
    return  redirect('/day22/login/')



=====setttyings.py======
SESSION_SAVE_EVERY_REQUEST = True

5.session存储位置设定:

1.settings.py中设置
a.存储到数据库中
SESSION_ENGINE = 'django.contrib.sessions.backends.db'  #session信息保存到数据库中
b.存储到缓存中
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS ='default'   #使用缓存别名(默认内存缓存,也可以是memcache)

CACHES = {
’default‘:{
              'BACKEND':'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION':[
       '172.19.26.240:11211',
       '172.19.26.242:11211',
]    
}  
’DB1‘:{
              'BACKEND':'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION':[
       '172.19.26.250:11211',
       '172.19.26.252:11211',
]    
}     
}
可以选择default,或者DB1连接,不能同时用。

c.存储到文件中
SESSION_ENGINE='django.contrib.sessions.backends.file'
SESSION_FILE_PATH = os.path.join(BASE_DIR,'cache')    #缓存文件路径,如果为None,则使用temfile模块
d.缓存+数据库中
SESSION_ENGINE ='django.contrib.sessions.backends.cached_db'

e.加密cookie版本
SESSION_ENGINE = ’django.contrib.sessions.backends.signed_cookies‘

二、CSRF使用                                                                                                                                                                    

1.ajax 提交CSRF

====login.html======
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action = "/day22/login/" method="post">
        {% csrf_token %}
        <input type="text" name="username" placeholder="用户名" />
        <input type="password" name="password" placeholder="密码" />
        <input type="checkbox" value="1" name="rmb" /> 超时时间10S
        <input type="submit" value="提交">
        <input id="btn" type="button" value="ajax提交">    
    </form>

<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
//ajax提交csrf方式
    $(function(){
        $.ajaxSetup({
            beforeSend:function(xhr,settings){
                xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken'));
            }
        });        //全局设置发送CSRFtoken

        $("#btn").click(function(){
            $.ajax({
                url:'/day22/login/',
                type:'POST',
                data:{'username':'root','password':'123'},
                //headers:{'X-CSRFtoken':$.cookie('csrftoken')},    //某个函数设置CSRFtoken
                success:function(arg){

                }
        });
    })
    })
</script>
</body>
</html>

2.form 使用csrf

全局:

django.middleware.csrf.CsrfViewMiddleware

局部:

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

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

三、中间件                                                                                                                                                       

       由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。   

       

Django中提供了6种缓存方式:

  • 开发调试
  • 内存
  • 文件
  • 数据库
  • Memcache缓存(python-memcached模块)
  • Memcache缓存(pylibmc模块)

1、配置

a、开发调试

# 此为开始调试用,实际内部不做任何操作
    # 配置:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.dummy.DummyCache',     # 引擎
                'TIMEOUT': 300,                                               # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
                'OPTIONS':{
                    'MAX_ENTRIES': 300,                                       # 最大缓存个数(默认300)
                    'CULL_FREQUENCY': 3,                                      # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
                },
                'KEY_PREFIX': '',                                             # 缓存key的前缀(默认空)
                'VERSION': 1,                                                 # 缓存key的版本(默认1)
                'KEY_FUNCTION' 函数名                                          # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
            }
        }


    # 自定义key
    def default_key_func(key, key_prefix, version):
        """
        Default function to generate keys.

        Constructs the key used by all other methods. By default it prepends
        the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
        function with custom key making behavior.
        """
        return '%s:%s:%s' % (key_prefix, version, key)

    def get_key_func(key_func):
        """
        Function to decide which key function to use.

        Defaults to ``default_key_func``.
        """
        if key_func is not None:
            if callable(key_func):
                return key_func
            else:
                return import_string(key_func)
        return default_key_func

b、内存

# 此缓存将内容保存至内存的变量中
    # 配置:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                'LOCATION': 'unique-snowflake',
            }
        }

    # 注:其他配置同开发调试版本

c、文件

  # 此缓存将内容保存至文件
    # 配置:

        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
                'LOCATION': '/var/tmp/django_cache',
            }
        }
    # 注:其他配置同开发调试版本

d、数据库

# 此缓存将内容保存至数据库

    # 配置:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
                'LOCATION': 'my_cache_table', # 数据库表
            }
        }

    # 注:执行创建表命令 python manage.py createcachetable

e、Memcache缓存(python-memcached模块)

# 此缓存使用python-memcached模块连接memcache

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': 'unix:/tmp/memcached.sock',
        }
    }   

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': [
                '172.19.26.240:11211',
                '172.19.26.242:11211',
            ]
        }
    }

f、Memcache缓存(pylibmc模块)

# 此缓存使用pylibmc模块连接memcache
    
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': '/tmp/memcached.sock',
        }
    }   

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': [
                '172.19.26.240:11211',
                '172.19.26.242:11211',
            ]
        }
    }

四、信号                                                                                                                                                                                                                            

1.django内置信号

Model signals
    pre_init                    # django的model执行其构造方法前,自动触发
    post_init                   # django的model执行其构造方法后,自动触发
    pre_save                    # django的model对象保存前,自动触发
    post_save                   # django的model对象保存后,自动触发
    pre_delete                  # django的model对象删除前,自动触发
    post_delete                 # django的model对象删除后,自动触发
    m2m_changed                 # django的model中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
    class_prepared              # 程序启动时,检测已注册的app中model类,对于每一个类,自动触发
Management signals
    pre_migrate                 # 执行migrate命令前,自动触发
    post_migrate                # 执行migrate命令后,自动触发
Request/response signals
    request_started             # 请求到来前,自动触发
    request_finished            # 请求结束后,自动触发
    got_request_exception       # 请求异常后,自动触发
Test signals
    setting_changed             # 使用test测试修改配置文件时,自动触发
    template_rendered           # 使用test测试渲染模板时,自动触发
Database Wrappers
    connection_created          # 创建数据库连接时,自动触发

对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

from django.core.signals import request_finished
    from django.core.signals import request_started
    from django.core.signals import got_request_exception

    from django.db.models.signals import class_prepared
    from django.db.models.signals import pre_init, post_init
    from django.db.models.signals import pre_save, post_save
    from django.db.models.signals import pre_delete, post_delete
    from django.db.models.signals import m2m_changed
    from django.db.models.signals import pre_migrate, post_migrate

    from django.test.signals import setting_changed
    from django.test.signals import template_rendered

    from django.db.backends.signals import connection_created


    def callback(sender, **kwargs):
        print("xxoo_callback")
        print(sender,kwargs)

    xxoo.connect(callback)
    # xxoo指上述导入的内容
from django.core.signals import request_finished
from django.dispatch import receiver

@receiver(request_finished)
def my_callback(sender, **kwargs):
    print("Request finished!")

2、自定义信号

a. 定义信号

import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

b. 注册信号

def callback(sender, **kwargs):
    print("callback")
    print(sender,kwargs)
 
pizza_done.connect(callback)

c.触发信号

from 路径 import pizza_done pizza_done.send(sender='seven',toppings=123, size=456)

 五、Form表单

1.Django 内置字段

Field

 1     required=True,               是否允许为空
 2     widget=None,                 HTML插件
 3     label=None,                  用于生成Label标签或显示内容
 4     initial=None,                初始值
 5     help_text='',                帮助信息(在标签旁边显示)
 6     error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}
 7     show_hidden_initial=False,   是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
 8     validators=[],               自定义验证规则
 9     localize=False,              是否支持本地化
10     disabled=False,              是否可以编辑
11     label_suffix=None            Label内容后缀

 

CharField(Field)

1   max_length=None,             最大长度
2   min_length=None,             最小长度
3   strip=True                   是否移除用户输入空白

 

IntegerField(Field)

1     max_value=None,              最大值
2     min_value=None,              最小值

FloatField(IntegerField)

DecimalField(IntegerField)

1     max_value=None,              最大值
2     min_value=None,              最小值
3     max_digits=None,             总长度
4     decimal_places=None,         小数位长度

BaseTemporalField(Field)

    input_formats=None          时间格式化
DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 
DurationField(Field)            时间间隔:%d %H:%M:%S.%f

DurationField(Field)            时间间隔:%%H:%M:%S.%f

RegexField(CharField)

1     regex,                      自定制正则表达式
2     max_length=None,            最大长度
3     min_length=None,            最小长度
4     error_message=None,         忽略,错误信息使用 error_messages={'invalid': '...'}

EmailField(CharField)   


FileField(Field)

allow_empty_file=False     是否允许空文件
 
ImageField(FileField)  
1  ...
2     注:需要PIL模块,pip3 install Pillow
3     以上两个字典使用时,需要注意两点:
4         - form表单中 enctype="multipart/form-data"
5         - view函数中 obj = MyForm(request.POST, request.FILES)

URLField(Field)

...

BooleanField(Field)  

...


NullBooleanField(BooleanField)

...

ChoiceField(Field)

1  ...
2     choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)
3     required=True,             是否必填
4     widget=None,               插件,默认select插件
5     label=None,                Label内容
6     initial=None,              初始值
7     help_text='',              帮助提示

ModelChoiceField(ChoiceField)

  ...                        django.forms.models.ModelChoiceField
    queryset,                  # 查询数据库中的数据
    empty_label="---------",   # 默认空显示内容
    to_field_name=None,        # HTML中value的值对应的字段
    limit_choices_to=None      # ModelForm中对queryset二次筛选

 ModelMultipleChoiceField(ModelChoiceField)

 ...                        django.forms.models.ModelMultipleChoiceField

TypedChoiceField(ChoiceField)

1  coerce = lambda val: val   对选中的值进行一次转换
2  empty_value= ''            空值的默认值

MultipleChoiceField(ChoiceField)

...

TypedMultipleChoiceField(MultipleChoiceField)

 coerce = lambda val: val   对选中的每一个值进行一次转换
 empty_value= ''            空值的默认值

ComboField(Field)

 fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式
                               fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])

MultiValueField(Field)

PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用

SplitDateTimeField(MultiValueField)

1     input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
2     input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']

FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中

 1     path,                      文件夹路径
 2     match=None,                正则匹配
 3     recursive=False,           递归下面的文件夹
 4     allow_files=True,          允许文件
 5     allow_folders=False,       允许文件夹
 6     required=True,
 7     widget=None,
 8     label=None,
 9     initial=None,
10     help_text=''

GenericIPAddressField

1     protocol='both',           both,ipv4,ipv6支持的IP格式
2     unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用

SlugField(CharField)           数字,字母,下划线,减号(连字符)
...

UUIDField(CharField)           uuid类型

...

注:UUID是根据MAC以及当前时间等创建的不重复的随机字符串

>>> import uuid

    # make a UUID based on the host ID and current time
    >>> uuid.uuid1()    # doctest: +SKIP
    UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')

    # make a UUID using an MD5 hash of a namespace UUID and a name
    >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
    UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')

    # make a random UUID
    >>> uuid.uuid4()    # doctest: +SKIP
    UUID('16fd2706-8baf-433b-82eb-8c7fada847da')

    # make a UUID using a SHA-1 hash of a namespace UUID and a name
    >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
    UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')

    # make a UUID from a string of hex digits (braces and hyphens ignored)
    >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')

    # convert a UUID to a string of hex digits in standard form
    >>> str(x)
    '00010203-0405-0607-0809-0a0b0c0d0e0f'

    # get the raw 16 bytes of the UUID
    >>> x.bytes
    b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'

    # make a UUID from a 16-byte string
    >>> uuid.UUID(bytes=x.bytes)
    UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')

 

2.Django内置插件

 1 TextInput(Input)
 2 NumberInput(TextInput)
 3 EmailInput(TextInput)
 4 URLInput(TextInput)
 5 PasswordInput(TextInput)
 6 HiddenInput(TextInput)
 7 Textarea(Widget)
 8 DateInput(DateTimeBaseInput)
 9 DateTimeInput(DateTimeBaseInput)
10 TimeInput(DateTimeBaseInput)
11 CheckboxInput
12 Select
13 NullBooleanSelect
14 SelectMultiple
15 RadioSelect
16 CheckboxSelectMultiple
17 FileInput
18 ClearableFileInput
19 MultipleHiddenInput
20 SplitDateTimeWidget
21 SplitHiddenDateTimeWidget
22 SelectDateWidget

常用选择插件

 1 #单radio,值为字符串
 2 # user = fields.CharField(
 3 #     initial=2,
 4 #     widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))
 5 # )
 6  
 7 # 单radio,值为字符串
 8 # user = fields.ChoiceField(
 9 #     choices=((1, '上海'), (2, '北京'),),
10 #     initial=2,
11 #     widget=widgets.RadioSelect
12 # )
13  
14 # 单select,值为字符串
15 # user = fields.CharField(
16 #     initial=2,
17 #     widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
18 # )
19  
20 # 单select,值为字符串
21 # user = fields.ChoiceField(
22 #     choices=((1, '上海'), (2, '北京'),),
23 #     initial=2,
24 #     widget=widgets.Select
25 # )
26  
27 # 多选select,值为列表
28 # user = fields.MultipleChoiceField(
29 #     choices=((1,'上海'),(2,'北京'),),
30 #     initial=[1,],
31 #     widget=widgets.SelectMultiple
32 # )
33  
34  
35 # 单checkbox
36 # user = fields.CharField(
37 #     widget=widgets.CheckboxInput()
38 # )
39  
40  
41 # 多选checkbox,值为列表
42 # user = fields.MultipleChoiceField(
43 #     initial=[2, ],
44 #     choices=((1, '上海'), (2, '北京'),),
45 #     widget=widgets.CheckboxSelectMultiple
46 # )

在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 ***获取的值无法实时更新***,那么需要自定义构造方法从而达到此目的。

方式一:

 1 from django.forms import Form
 2 from django.forms import widgets
 3 from django.forms import fields
 4 from django.core.validators import RegexValidator
 5  
 6 class MyForm(Form):
 7  
 8     user = fields.ChoiceField(
 9         # choices=((1, '上海'), (2, '北京'),),
10         initial=2,
11         widget=widgets.Select
12     )
13  
14     def __init__(self, *args, **kwargs):
15         super(MyForm,self).__init__(*args, **kwargs)
16         # self.fields['user'].widget.choices = ((1, '上海'), (2, '北京'),)
17         #
18         self.fields['user'].widget.choices = models.Classes.objects.all().value_list('id','caption')

方式二:

使用django提供的ModelChoiceField和ModelMultipleChoiceField字段来实现

 1 from django import forms
 2 from django.forms import fields
 3 from django.forms import widgets
 4 from django.forms import models as form_model
 5 from django.core.exceptions import ValidationError
 6 from django.core.validators import RegexValidator
 7  
 8 class FInfo(forms.Form):
 9     authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())
10     # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())

自定义验证规则:

方式一:

1 from django.forms import Form
2 from django.forms import widgets
3 from django.forms import fields
4 from django.core.validators import RegexValidator
5  
6 class MyForm(Form):
7     user = fields.CharField(
8         validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
9     )

方式二:

 1 import re
 2 from django.forms import Form
 3 from django.forms import widgets
 4 from django.forms import fields
 5 from django.core.exceptions import ValidationError
 6  
 7  
 8 # 自定义验证规则
 9 def mobile_validate(value):
10     mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
11     if not mobile_re.match(value):
12         raise ValidationError('手机号码格式错误')
13  
14  
15 class PublishForm(Form):
16  
17  
18     title = fields.CharField(max_length=20,
19                             min_length=5,
20                             error_messages={'required': '标题不能为空',
21                                             'min_length': '标题最少为5个字符',
22                                             'max_length': '标题最多为20个字符'},
23                             widget=widgets.TextInput(attrs={'class': "form-control",
24                                                           'placeholder': '标题5-20个字符'}))
25  
26  
27     # 使用自定义验证规则
28     phone = fields.CharField(validators=[mobile_validate, ],
29                             error_messages={'required': '手机不能为空'},
30                             widget=widgets.TextInput(attrs={'class': "form-control",
31                                                           'placeholder': u'手机号码'}))
32  
33     email = fields.EmailField(required=False,
34                             error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},
35                             widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))

方法三:自定义方法

 1 from django import forms
 2     from django.forms import fields
 3     from django.forms import widgets
 4     from django.core.exceptions import ValidationError
 5     from django.core.validators import RegexValidator
 6  
 7     class FInfo(forms.Form):
 8         username = fields.CharField(max_length=5,
 9                                     validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.', 'invalid')], )
10         email = fields.EmailField()
11  
12         def clean_username(self):
13             """
14             Form中字段中定义的格式匹配完之后,执行此方法进行验证
15             :return:
16             """
17             value = self.cleaned_data['username']
18             if "666" in value:
19                 raise ValidationError('666已经被玩烂了...', 'invalid')
20             return value

方式四:同时生成多个标签进行验证

 1 from django.forms import Form
 2 from django.forms import widgets
 3 from django.forms import fields
 4  
 5 from django.core.validators import RegexValidator
 6  
 7  
 8 ############## 自定义字段 ##############
 9 class PhoneField(fields.MultiValueField):
10     def __init__(self, *args, **kwargs):
11         # Define one message for all fields.
12         error_messages = {
13             'incomplete': 'Enter a country calling code and a phone number.',
14         }
15         # Or define a different message for each field.
16         f = (
17             fields.CharField(
18                 error_messages={'incomplete': 'Enter a country calling code.'},
19                 validators=[
20                     RegexValidator(r'^[0-9]+$', 'Enter a valid country calling code.'),
21                 ],
22             ),
23             fields.CharField(
24                 error_messages={'incomplete': 'Enter a phone number.'},
25                 validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid phone number.')],
26             ),
27             fields.CharField(
28                 validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.')],
29                 required=False,
30             ),
31         )
32         super(PhoneField, self).__init__(error_messages=error_messages, fields=f, require_all_fields=False, *args,
33                                          **kwargs)
34  
35     def compress(self, data_list):
36         """
37         当用户验证都通过后,该值返回给用户
38         :param data_list:
39         :return:
40         """
41         return data_list
42  
43 ############## 自定义插件 ##############
44 class SplitPhoneWidget(widgets.MultiWidget):
45     def __init__(self):
46         ws = (
47             widgets.TextInput(),
48             widgets.TextInput(),
49             widgets.TextInput(),
50         )
51         super(SplitPhoneWidget, self).__init__(ws)
52  
53     def decompress(self, value):
54         """
55         处理初始值,当初始值initial不是列表时,调用该方法
56         :param value:
57         :return:
58         """
59         if value:
60             return value.split(',')
61         return [None, None, None]

初始化数据

1、Form

 1 from django.forms import Form
 2 from django.forms import widgets
 3 from django.forms import fields
 4 from django.core.validators import RegexValidator
 5  
 6  
 7 class MyForm(Form):
 8     user = fields.CharField()
 9  
10     city = fields.ChoiceField(
11         choices=((1, '上海'), (2, '北京'),),
12         widget=widgets.Select
13     )

2、Views

 1 from django.shortcuts import render, redirect
 2 from .forms import MyForm
 3  
 4  
 5 def index(request):
 6     if request.method == "GET":
 7         values = {'user': 'root', 'city': 2}
 8         obj = MyForm(values)
 9  
10         return render(request, 'index.html', {'form': obj})
11     elif request.method == "POST":
12         return redirect('http://www.google.com')
13     else:
14         return redirect('http://www.google.com')

3、HTML

<form method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    <p>{{ form.user }} {{ form.user.errors }}</p>
    <p>{{ form.city }} {{ form.city.errors }}</p>
 
    <input type="submit"/>
</form>

 

posted @ 2017-01-10 16:07  jidi_78  阅读(75)  评论(0)    收藏  举报