Django入门(四)之Session操作、CSRF操作、自定义中间件、缓存、信号和Form组件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Dream_ya/article/details/87081838

上一篇文章>Django补充(三)之路由系统URL、自定义函数、自定义分页、Cookie操作、FBV和CBV

一、本机环境


操作系统:rhel7.3
Python版本:python3.6
Django版本:Django-2.1.5
[root@python _Django]# tree newproject
newproject
├── app
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       └── __init__.cpython-36.pyc
│   ├── models.py
│   ├── __pycache__
│   │   ├── admin.cpython-36.pyc
│   │   ├── __init__.cpython-36.pyc
│   │   └── models.cpython-36.pyc
│   ├── tests.py
│   └── views.py
├── db.sqlite3
├── manage.py
├── newproject
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   ├── settings.cpython-36.pyc
│   │   ├── urls.cpython-36.pyc
│   │   └── wsgi.cpython-36.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── static
│   ├── jquery-1.12.4.min.js
│   └── jquery.cookie-1.4.1.min.js
└── templates

二、Session操作


1、Session介绍

基于Cookie做验证时:敏感信息不适合放在cookie中!!!

  • Cookie是保存在用户浏览器端的键值对

  • Session是保存在服务器端的键值对

2、实现Session登陆

(1)配置urls.py
[root@python newproject]# vim newproject/urls.py
from django.contrib import admin
from django.urls import path
from app import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
]
(2)配置views.py
[root@python newproject]# vim app/views.py
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse

def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    elif request.method == "POST":
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        if user == "dream" and pwd == '1':
            ### 生成随机字符串,写到用户浏览器cookie
            ### 保存在session中,在随机字符串对应的字典中设置相关内容
            request.session['username'] = user
            request.session['is_login'] = True
            return redirect('/index')
        else:
            return render(request, 'login.html')
            
def index(request):
    ### 获取session中的值
    if request.session.get('is_login', None):
        return HttpResponse(request.session['username'])
    else:
        return HttpResponse('404 not Found')
(3)配置HTML
[root@python newproject]# vim templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login/" method="POST">
    <label>用户名:</label>
    <input type="text" name="user" />
    <br/>
    <label>密码:</label>
    <input type="password" name="pwd" />
    <input type="submit" value="提交" />
</form>
</body>
</html>
(4)访问
http://10.10.10.111:8000/login/

3、添加注销及session清除

(1)session参数
### 用户session随机字符串
request.session.session_key

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

### 检查用户session的随机字符串是否存在在数据库(默认)
request.session.exsists("session_key")

### 删除当前用户的所有session数据
request.session.delete("session_key")

### 删除某一条session数据
del request.session['k1']

### clear等同于
request.session.clear() ==>> request.session.delete(request.session.session_key)
(2)配置urls.py
[root@python newproject]# vim newproject/urls.py
from django.contrib import admin
from django.urls import path
from app import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('logout/', views.logout),
]
(3)配置views.py
[root@python newproject]# vim app/views.py
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse

def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    elif request.method == "POST":
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        if user == "dream" and pwd == '1':
            ### 生成随机字符串,写到用户浏览器cookie
            ### 保存在session中,在随机字符串对应的字典中设置相关内容
            request.session['username'] = user
            request.session['is_login'] = True
            return redirect('/index')
        else:
            return render(request, 'login.html')

def index(request):
    ### 获取session中的值
    if request.session.get('is_login', None):
        return render(request, 'index.html', {'username': request.session['username']})
    else:
        return HttpResponse('404 not Found')

def logout(request):
    ### 清除session
    request.session.clear()
    return redirect('/login/')
(4)配置HTML
[root@python newproject]# vim templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <!--获取二种方式-->
    <h1>欢迎登陆:{{ username }},{{ request.session.username }}</h1>
    <a href="/logout">logout</a>
</body>
</html>
(5)访问
http://10.10.10.111:8000/login/

4、设置登录超时时间

(1)配置views.py
[root@python newproject]# vim app/views.py
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse

def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    elif request.method == "POST":
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        if user == "dream" and pwd == '1':
            ### 生成随机字符串,写到用户浏览器cookie
            ### 保存在session中,在随机字符串对应的字典中设置相关内容
            request.session['username'] = user
            request.session['is_login'] = True
            if request.POST.get('savaValue', None) == '1':
                ### 设置超时时间为6s
                request.session.set_expiry(6)
            return redirect('/index')
        else:
            return render(request, 'login.html')

def index(request):
    ### 获取session中的值
    if request.session.get('is_login', None):
        return render(request, 'index.html', {'username': request.session['username']})
    else:
        return HttpResponse('404 not Found')

def logout(request):
    ### 清除session
    request.session.clear()
    return redirect('/login/')
(2)配置HTML
[root@python newproject]# vim templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login/" method="POST">
    <label>用户名:</label>
    <input type="text" name="user" />
    <br/>
    <label>密码:</label>
    <input type="password" name="pwd" />
    <br/>
    <input type="checkbox" name="savaValue" value="1" />6秒免登陆
    <input type="submit" value="提交" />
</form>
</body>
</html>
(3)访问

我们可以发现登陆后,6s后不能访问(即使我们在使用网站),这样在日常使用中是不科学的,我应该刷新网站会使网页超时时间也进行自动更改为当前时间后的6s!!!

http://10.10.10.111:8000/login/

5、登录超时时间自动刷新

(1)Session默认配置说明
配置文件中(settings.py )设置默认操作(通用配置):
		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过期(默认)
		# set_cookie('k',123)
		SESSION_SAVE_EVERY_REQUEST = False        ###是否每次请求都保存Session,默认修改之后才保存(默认)
(2)配置settings.py
[root@python newproject]# vim newproject/settings.py     ###在末尾添加此条即可
SESSION_SAVE_EVERY_REQUEST = True
(3)访问

访问可以发现我们在使用时,只要刷新页面页面就不会超时,6s不刷新页面便会超时!!!

http://10.10.10.111:8000/login/

6、设置Session保存位置(内部自带五种)

在settings.py中加入!!!

(1)数据库(默认)
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
(2)缓存
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'       ###使用的缓存别名(默认内存缓存,也可以是memcache)

eg.连接Memcache

[root@python newproject]# vim newproject/settings.py      ###末尾加入即可
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'

### 里面可以加多个连接
CACHES = {
	'default': {
		'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
		'LOCATION': [
			'10.10.10.1:11211',
			'10.10.10.2:11211',
		]
    }
}
(3)文件
SESSION_ENGINE = 'django.contrib.sessions.backends.file'
### 缓存文件路径,None表示使用tempfile模块获取一个临时地址tempfile.gettempdir()
SESSION_FILE_PATH = None
(4)缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cache_db'
(5)加密cookie
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'

三、CSRF操作


注意:这样是全局CSRF,所有都需要进过认证!!!

1、设置全局CSRF(配置settings.py

[root@python newproject]# vim newproject/settings.py      ###取消注释

在这里插入图片描述

2、CSRF简介

防止跨站请求伪造,黑客可以伪造用户访问,因此通过用户自己的cookie来通过安全验证,在用户HTTP请求中加入随机token进行验证!!!

3、Form表单提交方式(csrf_token)

(1)配置HTML
[root@python newproject]# vim templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login/" method="POST">
    {% csrf_token %}
    <label>用户名:</label>
    <input type="text" name="user" />
    <br/>
    <label>密码:</label>
    <input type="password" name="pwd" />
    <br/>
    <input type="checkbox" name="savaValue" value="1" />6秒免登陆
    <input type="submit" value="提交" />
</form>
</body>
</html>

可以发现我们现在在input中不输入内容提交也不会报错!!!
在这里插入图片描述

4、Ajax提交方式

(1)单个写法
[root@python newproject]# vim templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login/" method="POST">
    {% csrf_token %}
    <label>用户名:</label>
    <input type="text" name="user" />
    <br/>
    <label>密码:</label>
    <input type="password" name="pwd" />
    <br/>
    <input type="checkbox" name="savaValue" value="1" />6秒免登陆
    <input type="submit" value="提交" />
    <input id="1" type="button" value="Ajax提交">
</form>
<script src="/static/jquery-1.12.4.min.js"></script>
<script src="/static/jquery.cookie-1.4.1.min.js"></script>
<script>
    $(function () {
        $('#1').click(function () {
            $.ajax({
                url: '/login/',
                type: 'POST',
                data: {'user': 'dream', 'pwd': '1'},
                // 默认收到的消息会加HTTP_,且X-CSRFtoken中不能有_
                headers: {'X-CSRFtoken': $.cookie('csrftoken')},
                success: function (arg) {

                }
            })
        });
    })
</script>
</body>
</html>
(2)多个写法(优化)
[root@python newproject]# vim templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login/" method="POST">
    {% csrf_token %}
    <label>用户名:</label>
    <input type="text" name="user" />
    <br/>
    <label>密码:</label>
    <input type="password" name="pwd" />
    <br/>
    <input type="checkbox" name="savaValue" value="1" />6秒免登陆
    <input type="submit" value="提交" />
    <input id="1" type="button" value="Ajax提交">
</form>
<script src="/static/jquery-1.12.4.min.js"></script>
<script src="/static/jquery.cookie-1.4.1.min.js"></script>
<script>
    $(function () {
        // 把header统一写好,多个ajax提交也不用重写
        $.ajaxSetup({
           beforeSend: function (xhr, settings) {
               xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'));
           }
        });

        $('#1').click(function () {
            $.ajax({
                url: '/login/',
                type: 'POST',
                data: {'user': 'dream', 'pwd': '1'},
                // 默认收到的消息会加HTTP_,且X-CSRFtoken中不能有_
                // headers: {'X-CSRFtoken': $.cookie('csrftoken')},
                success: function (arg) {

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

5、局部CSRF设置

### 在views中通过from导入,然后装饰设置函数
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_protect        ###当前函数设置CSRF,我就把setting中的CSRF注释掉
@csrf_exempt         ###当前函数取消CSRF,把setting中的CSRF打开

6、CSRF判断

[root@python newproject]# vim templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login/" method="POST">
    {% csrf_token %}
    <label>用户名:</label>
    <input type="text" name="user" />
    <br/>
    <label>密码:</label>
    <input type="password" name="pwd" />
    <br/>
    <input type="checkbox" name="savaValue" value="1" />6秒免登陆
    <input type="submit" value="提交" />
    <input id="1" type="button" value="Ajax提交">
</form>
<script src="/static/jquery-1.12.4.min.js"></script>
<script src="/static/jquery.cookie-1.4.1.min.js"></script>
<script>
    // 这样我们可以实现不符合要求的提交不进行CSRF
    $(function () {
        function csrfSafeMethod(method){
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method))
        };
        
        // 把header统一写好,多个ajax提交也不用重写
        $.ajaxSetup({
           beforeSend: function (xhr, settings) {
               // xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'));
               if (!csrfSafeMethod(settings.type) && !this.crossDomain){
                   xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'));
               }
           }
        });

        $('#1').click(function () {
            $.ajax({
                url: '/login/',
                type: 'POST',
                data: {'user': 'dream', 'pwd': '1'},
                // 默认收到的消息会加HTTP_
                // headers: {'X-CSRFtoken': $.cookie('csrftoken')},
                success: function (arg) {

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

四、自定义中间件


1、process_request和process_response操作

通过process_request发送,process_response回应,中间件就是一层一层传输,然后在在一层一层回应!!!

(1)配置m1.py
[root@python newproject]# mkdir Middle
[root@python newproject]# vim Middle/m1.py
#!/usr/bin/env python
# coding:utf-8
from django.utils.deprecation import MiddlewareMixin
class Middle1(MiddlewareMixin):
    ### 请求进来经过
    def process_request(self, request):
        print ('process_request Middle1')

    def process_response(self, request, response):
        print ('process_response Middle1')
        return response

class Middle2(MiddlewareMixin):
    def process_request(self, request):
        print ('process_request Middle2')

    def process_response(self, request, response):
        print ('process_response Middle2')
        return response

class Middle3(MiddlewareMixin):
    def process_request(self, request):
        print ('process_request Middle3')

    def process_response(self, request, response):
        print ('process_response Middle3')
        return response
(2)加入test网址
[root@python newproject]# vim newproject/urls.py
from django.contrib import admin
from django.urls import path
from app import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('logout/', views.logout),
    path('test/', views.test),
]
[root@python newproject]# vim app/views.py       ###在末尾加入
def test(request):
    print ('test')
    return HttpResponse('OK')
[root@python newproject]# vim newproject/settings.py

在这里插入图片描述

(3)访问并查看结果
http://10.10.10.111:8000/test/

在这里插入图片描述

2、process_view操作

process_request后,从头开始执行process_view!!!

(1)配置m1.py
[root@python newproject]# vim Middle/m1.py
#!/usr/bin/env python
# coding:utf-8
from django.utils.deprecation import MiddlewareMixin
class Middle1(MiddlewareMixin):
    ### 请求进来经过
    def process_request(self, request):
        print ('process_request Middle1')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle1")

    def process_response(self, request, response):
        print ('process_response Middle1')
        return response

class Middle2(MiddlewareMixin):
    def process_request(self, request):
        print ('process_request Middle2')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle2")

    def process_response(self, request, response):
        print ('process_response Middle2')
        return response

class Middle3(MiddlewareMixin):
    def process_request(self, request):
        print ('process_request Middle3')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle3")
        
    def process_response(self, request, response):
        print ('process_response Middle3')
        return response
(2)访问并查看结果
http://10.10.10.111:8000/test/

在这里插入图片描述

(3)获取值view_func_args

<1> 配置urls.py

[root@python newproject]# vim newproject/urls.py
from django.contrib import admin
from django.urls import path, re_path
from app import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('logout/', views.logout),
    re_path('test/(\d+)', views.test),
]

<2> 配置m1.py

[root@python newproject]# vim Middle/m1.py
#!/usr/bin/env python
# coding:utf-8
from django.utils.deprecation import MiddlewareMixin
class Middle1(MiddlewareMixin):
    ### 请求进来经过
    def process_request(self, request):
        print ('process_request Middle1')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle1")

    def process_response(self, request, response):
        print ('process_response Middle1')
        return response

class Middle2(MiddlewareMixin):
    def process_request(self, request):
        print ('process_request Middle2')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle2")
        print (view_func, view_func_args, view_func_kwargs)

    def process_response(self, request, response):
        print ('process_response Middle2')
        return response

class Middle3(MiddlewareMixin):
    def process_request(self, request):
        print ('process_request Middle3')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle3")

    def process_response(self, request, response):
        print ('process_response Middle3')
        return response

<3> 访问并查看结果

http://10.10.10.111:8000/test/1

在这里插入图片描述

(4)获取值view_func_kwargs

<1> 配置urls.py

[root@python newproject]# vim newproject/urls.py
from django.contrib import admin
from django.urls import path, re_path
from app import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('logout/', views.logout),
    re_path('test/(?P<nid>\d+)', views.test),
]

<2> 访问并查看结果

http://10.10.10.111:8000/test/1

在这里插入图片描述

3、process_exception操作

不会直接运行当views中有报错才会运行!!!

(1)配置m1.py
[root@python newproject]# vim Middle/m1.py
#!/usr/bin/env python
# coding:utf-8
from django.utils.deprecation import MiddlewareMixin
class Middle1(MiddlewareMixin):
    ### 请求进来经过
    def process_request(self, request):
        print ('process_request Middle1')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle1")

    def process_response(self, request, response):
        print ('process_response Middle1')
        return response

class Middle2(MiddlewareMixin):
    def process_request(self, request):
        print ('process_request Middle2')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle2")
        print (view_func, view_func_args, view_func_kwargs)

    def process_response(self, request, response):
        print ('process_response Middle2')
        return response

class Middle3(MiddlewareMixin):
    def process_request(self, request):
        print ('process_request Middle3')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle3")

    def process_response(self, request, response):
        print ('process_response Middle3')
        return response

    ### 添加process_exception
    def process_exception(self, request, exception):
        print ('process_exception Middle3')
(2)配置views.py
[root@python newproject]# vim app/views.py
def test(request,nid):
    ### 此处报错
    int('dreamya')
    print ('test')
    return HttpResponse('OK')
(3)访问并查看结果
http://10.10.10.111:8000/test/1

在这里插入图片描述

(4)进行错误处理

<1> 配置m1.py

[root@python newproject]# vim Middle/m1.py
#!/usr/bin/env python
# coding:utf-8
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class Middle1(MiddlewareMixin):
    ### 请求进来经过
    def process_request(self, request):
        print ('process_request Middle1')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle1")

    def process_response(self, request, response):
        print ('process_response Middle1')
        return response

class Middle2(MiddlewareMixin):
    def process_request(self, request):
        print ('process_request Middle2')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle2")
        print (view_func, view_func_args, view_func_kwargs)

    def process_response(self, request, response):
        print ('process_response Middle2')
        return response

class Middle3(MiddlewareMixin):
    def process_request(self, request):
        print ('process_request Middle3')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle3")

    def process_response(self, request, response):
        print ('process_response Middle3')
        return response

    def process_exception(self, request, exception):
        # print ('process_exception Middle3')
        if isinstance(exception, ValueError):
            return HttpResponse("异常错误!!!")

<2> 访问并查看结果

http://10.10.10.111:8000/test/1

在这里插入图片描述
在这里插入图片描述

4、process_template_response操作

如果Viess中的函数中返回的对象中有render方法,就会运行!!!

(1)配置views.py
[root@python newproject]# vim app/views.py
class F:
    def render(self):
        return HttpResponse('OK')

def test(request,nid):
    print ('test')
    return F()
(2)配置m1.py
[root@python newproject]# vim Middle/m1.py
#!/usr/bin/env python
# coding:utf-8
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class Middle1(MiddlewareMixin):
    ### 请求进来经过
    def process_request(self, request):
        print ('process_request Middle1')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle1")

    def process_response(self, request, response):
        print ('process_response Middle1')
        return response

class Middle2(MiddlewareMixin):
    def process_request(self, request):
        print ('process_request Middle2')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle2")
        print (view_func, view_func_args, view_func_kwargs)

    def process_response(self, request, response):
        print ('process_response Middle2')
        return response

class Middle3(MiddlewareMixin):
    def process_request(self, request):
        print ('process_request Middle3')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print ("process_view Middle3")

    def process_response(self, request, response):
        print ('process_response Middle3')
        return response

    def process_exception(self, request, exception):
        # print ('process_exception Middle3')
        if isinstance(exception, ValueError):
            return HttpResponse("异常错误!!!")

    def process_template_response(self, request, response):
        print ('process_template_response Middle3')
        return response
(3)访问并查看结果
http://10.10.10.111:8000/test/1

在这里插入图片描述
五、缓存


1、五种配置

(1)开发调试
CACHES = {
	'default': {
		'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
		'TIMEOUT': 300,       ###超时时间,默认300s
	'OPTIONS':{
		'MAX_ENTRIES': 300,          ###最大缓存个数,默认300
		'CULL_FREQUENCY': 3,      ###缓存达到最大缓存个数时,删除换出1/3,这里默认值为3
		},
		'KEY_PREFIX': '',              ###缓存key的前缀,默认为空
		'VERSION': 1,             ###缓存key版本,默认为1
		'KEY_FUNCTION':"func_name"   ###生成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
(2)内存
CACHES = {
	'default': {
	   'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
	   'LOCATION': 'unique-snowflake',     ###设置一个唯一值
	}
	###其他的配置和开发调试版本一样
}
(3)文件
CACHES = {
	'default': {
	    'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
	    'LOCATION': '/var/tmp/django_cache',  #缓存存放的路径<br>    
	}
	###其他的配置和开发调试版本一样
}
(4)数据库
CACHES = {
	'default': {
	    'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
	    'LOCATION': 'my_cache_table',    ###设置一个数据库存放缓存的表名
	}
	###其他的配置和开发调试版本一样
}
### 注:执行创建表命令 python manage.py createcachetable
(5)Memcache缓存

<1> 通过python-memcached模块链接

### 单台机器
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': [
            '10.10.10.1:11211',
            '10.10.10.2:11211',
           ### 设置权重
           ###('10.10.10.1:11211',10),
           ###('10.10.10.2:11211',20),
        ]   
    }
    ###其他的配置和开发调试版本一样
}

<2> 通过pylibmc模块链接

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': [
           '10.10.10.1:11211',
           '10.10.10.2:11211',
       ]
   }
}

2、三种应用

(1)单独视图缓存
[root@python newproject]# vim newproject/urls.py
from django.contrib import admin
from django.urls import path, re_path
from app import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('logout/', views.logout),
    re_path('test/(?P<nid>\d+)', views.test),
    path('cache/', views.cache),
]
[root@python newproject]# vim newproject/settings.py  ###在末尾加入
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': os.path.join(BASE_DIR, 'cache'),
    }
}
[root@python newproject]# vim app/views.py
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse
def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    elif request.method == "POST":
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        if user == "dream" and pwd == '1':
            ### 生成随机字符串,写到用户浏览器cookie
            ### 保存在session中,在随机字符串对应的字典中设置相关内容
            request.session['username'] = user
            request.session['is_login'] = True
            if request.POST.get('savaValue', None) == '1':
                request.session.set_expiry(6)
            return redirect('/index')
        else:
            return render(request, 'login.html')

def index(request):
    ### 获取session中的值
    if request.session.get('is_login', None):
        return render(request, 'index.html', {'username': request.session['username']})
    else:
        return HttpResponse('404 not Found')

def logout(request):
    ### 清除session
    request.session.clear()
    return redirect('/login/')

class F:
    def render(self):
        return HttpResponse('OK')

def test(request,nid):
    print ('test')
    return F()
    
from django.views.decorators.cache import cache_page
### 缓存10s,默认300s
@cache_page(10)
def cache(request):
    import time
    ctime = time.time()
    return render(request, 'cache.html', { 'ctime': ctime, })
[root@python newproject]# vim templates/cache.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {{ ctime }}
    {{ ctime }}
</body>
</html>

建立cache目录并访问

我们可以发现10s后在刷新数字才会改变!!!

[root@python newproject]# mkdir cache
http://10.10.10.111:8000/cache/
(2)局部视图缓存
[root@python newproject]# vim app/views.py     ###注释

在这里插入图片描述

[root@python newproject]# vim templates/cache.html
{% load cache %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {{ ctime }}
    {% cache 10 c1 %}
        {{ ctime }}
    {% endcache %}
</body>
</html>

访问并查看结果

http://10.10.10.111:8000/cache/

在这里插入图片描述

(3)全局视图缓存
[root@python newproject]# vim newproject/settings.py    ###在中间件的首尾加入
MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',
	...
    'django.middleware.cache.FetchFromCacheMiddleware',
]

六、信号


1、内置信号

(1)参数说明
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_startd         ###请求到来前
	request_finished       ###请求结束后
	got_request_exception  ###请求异常后

Test signals
	setting_changed        ###使用test测试修改配置文件时
	templates_rendered     ###使用test测试渲染模板时

Database Wrappers
	connection_created     ###创建数据库连接时
(2)实例使用
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 f1(sender, **kwargs):
        print("xxoo_callback")
        # print(sender,kwargs)
pre_save.connect(f1)
(3)使用方法

<1> 配置urls.py

[root@python newproject]# vim newproject/urls.py
from django.contrib import admin
from django.urls import path, re_path
from app import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('logout/', views.logout),
    re_path('test/(?P<nid>\d+)', views.test),
    path('cache/', views.cache),
    path('signal/', views.signal),
]

<2> 配置views.py

[root@python newproject]# vim app/views.py     ###添加
def signal(request):
    from app import models
    obj = models.UserInfo(user='root')
    print('end')
    obj.save()
    return HttpResponse('OK')

<3> 配置models.py

[root@python newproject]# vim app/models.py
from django.db import models
class UserInfo(models.Model):
    user = models.CharField(max_length=32)

<4> 配置sg.py

[root@python newproject]# vim sg.py
#!/usr/bin/env python
#coding:utf-8
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 fun(sender,**kwargs):
    print ("fun")
    print (sender,kwargs)
pre_save.connect(fun)
[root@python newproject]# vim newproject/__init__.py
import sg

<5> 启动访问

[root@python newproject]# python manage.py makemigrations
[root@python newproject]# python manage.py migrate
[root@python newproject]# python manage.py runserver 10.10.10.111:8000
http://10.10.10.111:8000/signal/

在这里插入图片描述

2、自定义信号

自定义信号需要开发者在任意位置触发(比如报警值超过阈值触发)!!!

(1)定义信号(sg.py
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])
(2)注册信号(sg.py
def callback(sender, **kwargs):
    print("callback")
    print(sender,kwargs)
pizza_done.connect(callback)
(3)触发信号(app/views.py的signal函数)
[root@python newproject]# vim app/views.py
from sg import pizza_done
pizza_done.send(sender="dream",toppings=123, size=456)

七、Form组件


1、注释掉之前的中间件

[root@python newproject]# vim newproject/settings.py

在这里插入图片描述

2、Form验证

(1)配置urls.py
[root@python newproject]# vim newproject/urls.py
from django.contrib import admin
from django.urls import path, re_path
from app import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('logout/', views.logout),
    re_path('test/(?P<nid>\d+)', views.test),
    path('cache/', views.cache),
    path('signal/', views.signal),
    path('fm/', views.fm),
]
(2)配置views.py
[root@python newproject]# vim app/views.py
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse
...
from django import forms
class FM(forms.Form):
    ### 跟HTML中的name一样
    user = forms.CharField()
    pwd = forms.CharField()
    email = forms.EmailField()

def fm(request):
    if request.method == "GET":
        return render(request,'fm.html')
    elif request.method == "POST":
        obj = FM(request.POST)
        ### res为True或False
        res = obj.is_valid()
        if res:
            ### 正确信息
            print (obj.cleaned_data)
        else:
            print (obj.errors)
            print (obj.errors.as_json())
        return redirect('/fm/')
(3)配置HTMl
[root@python newproject]# vim templates/fm.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/fm/" method="POST">
        {% csrf_token %}
        <p><input type="text" name="user"></p>
        <p><input type="text" name="pwd"></p>
        <p><input type="text" name="email"></p>
        <input type="submit" value="提交">
    </form>
</body>
</html>
(4)刷新页面提交后结果
http://10.10.10.111:8000/fm/

在这里插入图片描述

3、验证并显示错误信息

(1)配置views.py
[root@python newproject]# vim app/views.py
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse
...
from django import forms
class FM(forms.Form):
    ### 跟HTML中的name一样
    user = forms.CharField(error_messages={'required': "用户名不能为空"})
    pwd = forms.CharField(
        max_length = 12,
        min_length = 6,
        error_messages={'required': "密码不能为空", 'min_length':'密码长度不小于6', 'max_length': '密码长度不大于12'}
    )
    email = forms.EmailField(error_messages={'required': "邮箱不能为空", 'invalid':"邮箱格式错误"})

from app import models
def fm(request):
    if request.method == "GET":
        obj = FM()
        return render(request,'fm.html', {'obj': obj})
    elif request.method == "POST":
        obj = FM(request.POST)
        ### res为True或False
        res = obj.is_valid()
        if res:
            ### 正确信息
            print (obj.cleaned_data)
            ### 我们可以通过下面的方式写入到数据库中(字典格式)
            # models.UserInfo.objects.create(**obj.cleaned_data)
        else:
            # print (obj.errors['user'][0])
            # print (obj.errors.as_json())
            return render(request, 'fm.html', {'obj': obj})
        return redirect('/fm/')
(2)配置fm.html
[root@python newproject]# vim templates/fm.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/fm/" method="POST">
        {% csrf_token %}
        <!--<p><input type="text" name="user">{{ obj.errors.user.0 }}</p>-->
        <!--<p><input type="text" name="pwd">{{ obj.errors.pwd.0 }}</p>-->
        <!--<p><input type="text" name="email">{{ obj.errors.email.0 }}</p>-->
        <!--自动生成input标签-->
        <p>{{ obj.user }} {{ obj.errors.user.0 }}</p>
        <p>{{ obj.pwd }} {{ obj.errors.pwd.0 }}</p>
        <p>{{ obj.email }} {{ obj.errors.email.0 }}</p>
        <input type="submit" value="提交">
    </form>
</body>
</html>

4、简单方式(三种)

缺点:不方便自己定制!!!

(1)as_p方法
[root@python newproject]# vim templates/fm.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/fm/" method="POST">
        {% csrf_token %}
        {{ obj.as_p }}
        <input type="submit" value="提交">
    </form>
</body>
</html>
(2)as_ul方法
[root@python newproject]# vim templates/fm.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/fm/" method="POST">
        {% csrf_token %}
        {{ obj.as_ul }}
        <input type="submit" value="提交">
    </form>
</body>
</html>
(3)as_table方法
[root@python newproject]# vim templates/fm.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/fm/" method="POST">
        {% csrf_token %}
        <table>
            {{ obj.as_table }}
        </table>
        <input type="submit" value="提交">
    </form>
</body>
</html>

5、设置样式

(1)配置views.py
[root@python newproject]# vim app/views.py
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse
...
from django import forms
from django.forms import widgets
from django.forms import fields
class FM(forms.Form):
    ### 跟HTML中的name一样
    user = fields.CharField(
        error_messages={'required': "用户名不能为空"},
        widget = widgets.Textarea(attrs={'class': 'c1',})
        )
    pwd = fields.CharField(
        max_length = 12,
        min_length = 6,
        error_messages={
            'required': "密码不能为空",
            'min_length':'密码长度不小于6',
            'max_length': '密码长度不大于12'
            },
        # widget = widgets.PasswordInput
        widget = widgets.PasswordInput(attrs={'class':"c2",}),
    )
    email = fields.EmailField(error_messages={'required': "邮箱不能为空", 'invalid':"邮箱格式错误"})

from app import models
def fm(request):
    if request.method == "GET":
        obj = FM()
        return render(request,'fm.html', {'obj': obj})
    elif request.method == "POST":
        obj = FM(request.POST)
        ### res为True或False
        res = obj.is_valid()
        if res:
            ### 正确信息
            print (obj.cleaned_data)
            # models.UserInfo.objects.create(**obj.cleaned_data)
        else:
            # print (obj.errors['user'][0])
            # print (obj.errors.as_json())
            return render(request, 'fm.html', {'obj': obj})
        return redirect('/fm/')
(2)查看结果

在这里插入图片描述

6、Django内置字段

Field
	required=True,               ###是否允许为空
	widget=None,                 ###HTML插件
	label=None,                  ###用于生成Label标签或显示内容
	initial=None,                ###初始值
	help_text='',                ###帮助信息(在标签旁边显示)
	error_messages=None,         ###错误信息 {'required': '不能为空', 'invalid': '格式错误'}
	validators=[],               ###自定义验证规则
	localize=False,              ###是否支持本地化
	disabled=False,              ###是否可以编辑
	label_suffix=None            ###Label内容后缀

CharField(Field)
	max_length=None,             ###最大长度
	min_length=None,             ###最小长度
	strip=True                   ###是否移除用户输入空白

IntegerField(Field)
	max_value=None,              ###最大值
	min_value=None,              ###最小值

FloatField(IntegerField)
    ...
 
DecimalField(IntegerField)
	max_value=None,              ###最大值
	min_value=None,              ###最小值
	max_digits=None,             ###总长度
	decimal_places=None,         ###小数位长度
 
BaseTemporalField(Field)
	input_formats=None           ###时间格式化   

DateField(BaseTemporalField)      格式:2019-02-21
TimeField(BaseTemporalField)      格式:18:12
DateTimeField(BaseTemporalField)  格式:2019-02-21 18:12
DurationField(Field)              时间间隔:%d %H:%M:%S.%f
    ...
 
RegexField(CharField)
	regex,                      ###自定制正则表达式
	max_length=None,            ###最大长度
	min_length=None,            ###最小长度
	error_message=None,         ###忽略,错误信息使用 error_messages={'invalid': '...'}
 
EmailField(CharField)      
    ...
 
FileField(Field)
	allow_empty_file=False     ###是否允许空文件
 
ImageField(FileField)      
    ...
    注:需要PIL模块,pip3 install Pillow
    以上两个字典使用时,需要注意两点:
        - form表单中 enctype="multipart/form-data"
        - view函数中 obj = MyForm(request.POST, request.FILES)
 
URLField(Field)
    ...

BooleanField(Field)  
    ...
 
NullBooleanField(BooleanField)
    ...
 
ChoiceField(Field)
    ...
	choices=(),                ###选项,如:choices = ((0,'四川'),(1,'浙江'),)
	required=True,             ###是否必填
	widget=None,               ###插件,默认select插件
	label=None,                ###Label内容
	initial=None,              ###初始值
	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)
	coerce = lambda val: val   ###对选中的值进行一次转换
	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)
	input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
	input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
 
FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中
	path,                      ###文件夹路径
	match=None,                ###正则匹配
	recursive=False,           ###递归下面的文件夹
	allow_files=True,          ###允许文件
	allow_folders=False,       ###允许文件夹
	required=True,
	widget=None,
	label=None,
	 initial=None,
	 help_text=''

GenericIPAddressField
	protocol='both',           ###both,ipv4,ipv6支持的IP格式
	unpack_ipv4=False          ###解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
 
SlugField(CharField)           ###数字,字母,下划线,减号(连字符)
    ...
 
UUIDField(CharField)           ###uuid类型

7、Django内置插件

TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget

8、使用示例

(1)配置views.py
[root@python newproject]# vim app/views.py
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse
...
from django import forms
from django.forms import widgets
from django.forms import fields
class FM(forms.Form):
    ### 跟HTML中的name一样
    user = fields.CharField(
        error_messages={'required': "用户名不能为空"},
        widget = widgets.Textarea(attrs={'class': 'c1',}),
        initial = 'dreamya',
        )
    pwd = fields.CharField(
        max_length = 12,
        min_length = 6,
        error_messages={
            'required': "密码不能为空",
            'min_length':'密码长度不小于6',
            'max_length': '密码长度不大于12'
            },
        # widget = widgets.PasswordInput
        widget = widgets.PasswordInput(attrs={'class':"c2",}),
    )
    email = fields.EmailField(error_messages={'required': "邮箱不能为空", 'invalid':"邮箱格式错误"})
    p = fields.FilePathField(path='app')
    province = fields.ChoiceField(
        choices=[(0,'四川'),(1,'浙江'),(2,'福建')]
    )
    province1 = fields.MultipleChoiceField(
        choices=[(0,'四川'),[1,'浙江'],(2,'福建')]
    )
    
from app import models
def fm(request):
    if request.method == "GET":
        obj = FM()
        return render(request,'fm.html', {'obj': obj})
    elif request.method == "POST":
        obj = FM(request.POST)
        ### res为True或False
        res = obj.is_valid()
        if res:
            ### 正确信息
            print (obj.cleaned_data)
            # models.UserInfo.objects.create(**obj.cleaned_data)
        else:
            # print (obj.errors['user'][0])
            # print (obj.errors.as_json())
            return render(request, 'fm.html', {'obj': obj})
        return redirect('/fm/')
(2)配置fm.html
[root@python newproject]# vim templates/fm.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/fm/" method="POST">
        {% csrf_token %}
        <p>{{ obj.user }} {{ obj.errors.user.0 }}</p>
        <p>{{ obj.pwd }} {{ obj.errors.pwd.0 }}</p>
        <p>{{ obj.email }} {{ obj.errors.email.0 }}</p>
        <input type="submit" value="提交">
    </form>
    <!--app目录下文件-->
    {{ obj.p }}
    {{ obj.province }}
    {{ obj.province1 }}
</body>
</html>

9、初始化操作

(1)配置views.py
[root@python newproject]# vim app/views.py
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse
...
from django import forms
from django.forms import widgets
from django.forms import fields
class FM(forms.Form):
    ### 跟HTML中的name一样
    user = fields.CharField(
        error_messages={'required': "用户名不能为空"},
        widget = widgets.Textarea(attrs={'class': 'c1',}),
        initial = 'dreamya'
        )
    pwd = fields.CharField(
        max_length = 12,
        min_length = 6,
        error_messages={
            'required': "密码不能为空",
            'min_length':'密码长度不小于6',
            'max_length': '密码长度不大于12'

            },
        # widget = widgets.PasswordInput
        widget = widgets.PasswordInput(attrs={'class':"c2",}),
    )
    email = fields.EmailField(error_messages={'required': "邮箱不能为空", 'invalid':"邮箱格式错误"})
    p = fields.FilePathField(path='app')
    province = fields.ChoiceField(
        choices=[(0,'四川'),(1,'浙江'),(2,'福建')]
    )
    province1 = fields.MultipleChoiceField(
        choices=[(0,'四川'),[1,'浙江'],(2,'福建')]
    )
from app import models
def fm(request):
    if request.method == "GET":
        ### 从数据拿到数据,这里我们设置个字典相当于取出来的数据
        d = {
            'user': 'dream',
            'pwd': '123',
            'email': '[email protected]',
            'province': 1,
            'province1': [1,2],
        }
        obj = FM(initial=d)
        return render(request,'fm.html', {'obj': obj})
    elif request.method == "POST":
        obj = FM(request.POST)
        ### res为True或False
        res = obj.is_valid()
        if res:
            ### 正确信息
            print (obj.cleaned_data)
            # models.UserInfo.objects.create(**obj.cleaned_data)
        else:
            # print (obj.errors['user'][0])
            # print (obj.errors.as_json())
            return render(request, 'fm.html', {'obj': obj})
        return redirect('/fm/')
(2)配置fm.html
[root@python newproject]# vim templates/fm.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/fm/" method="POST">
        {% csrf_token %}
        <p>{{ obj.user }} {{ obj.errors.user.0 }}</p>
        <p>{{ obj.pwd }} {{ obj.errors.pwd.0 }}</p>
        <p>{{ obj.email }} {{ obj.errors.email.0 }}</p>
        <input type="submit" value="提交">
    </form>
    <!--app目录下文件-->
    {{ obj.p }}
    {{ obj.province }}
    {{ obj.province1 }}
</body>
</html>
(3)查看结果

在这里插入图片描述
下一篇文章>Django入门(五)之ModelForm操作、原生Ajax、伪Ajax、文件上传和图片验证码生成

猜你喜欢

转载自blog.csdn.net/Dream_ya/article/details/87081838