上一篇文章
>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
基于Cookie做验证时:敏感信息不适合放在cookie中!!!
Cookie是保存在用户浏览器端的键值对
Session是保存在服务器端的键值对
[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),
]
[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')
[root@python newproject]# vim templates/login.html
Title
http://10.10.10.111:8000/login/
### 用户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)
[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),
]
[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/')
[root@python newproject]# vim templates/index.html
Title
欢迎登陆:{{ username }},{{ request.session.username }}
logout
http://10.10.10.111:8000/login/
[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/')
[root@python newproject]# vim templates/login.html
Title
我们可以发现登陆后,6s后不能访问(即使我们在使用网站),这样在日常使用中是不科学的,我应该刷新网站会使网页超时时间也进行自动更改为当前时间后的6s!!!
http://10.10.10.111:8000/login/
配置文件中(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,默认修改之后才保存(默认)
[root@python newproject]# vim newproject/settings.py ###在末尾添加此条即可
SESSION_SAVE_EVERY_REQUEST = True
访问可以发现我们在使用时,只要刷新页面页面就不会超时,6s不刷新页面便会超时!!!
http://10.10.10.111:8000/login/
在settings.py中加入!!!
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
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',
]
}
}
SESSION_ENGINE = 'django.contrib.sessions.backends.file'
### 缓存文件路径,None表示使用tempfile模块获取一个临时地址tempfile.gettempdir()
SESSION_FILE_PATH = None
SESSION_ENGINE = 'django.contrib.sessions.backends.cache_db'
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
注意:这样是全局CSRF,所有都需要进过认证!!!
[root@python newproject]# vim newproject/settings.py ###取消注释
防止跨站请求伪造,黑客可以伪造用户访问,因此通过用户自己的cookie来通过安全验证,在用户HTTP请求中加入随机token进行验证!!!
[root@python newproject]# vim templates/login.html
Title
可以发现我们现在在input中不输入内容提交也不会报错!!!
[root@python newproject]# vim templates/login.html
Title
[root@python newproject]# vim templates/login.html
Title
### 在views中通过from导入,然后装饰设置函数
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_protect ###当前函数设置CSRF,我就把setting中的CSRF注释掉
@csrf_exempt ###当前函数取消CSRF,把setting中的CSRF打开
[root@python newproject]# vim templates/login.html
Title
通过process_request发送,process_response回应,中间件就是一层一层传输,然后在在一层一层回应!!!
[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
[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
http://10.10.10.111:8000/test/
process_request后,从头开始执行process_view!!!
[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
http://10.10.10.111:8000/test/
<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
<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\d+)', views.test),
]
<2> 访问并查看结果
http://10.10.10.111:8000/test/1
不会直接运行当views中有报错才会运行!!!
[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')
[root@python newproject]# vim app/views.py
def test(request,nid):
### 此处报错
int('dreamya')
print ('test')
return HttpResponse('OK')
http://10.10.10.111:8000/test/1
<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
如果Viess中的函数中返回的对象中有render方法,就会运行!!!
[root@python newproject]# vim app/views.py
class F:
def render(self):
return HttpResponse('OK')
def test(request,nid):
print ('test')
return F()
[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
http://10.10.10.111:8000/test/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
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake', ###设置一个唯一值
}
###其他的配置和开发调试版本一样
}
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache', #缓存存放的路径
}
###其他的配置和开发调试版本一样
}
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table', ###设置一个数据库存放缓存的表名
}
###其他的配置和开发调试版本一样
}
### 注:执行创建表命令 python manage.py createcachetable
<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',
]
}
}
[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\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
Title
{{ ctime }}
{{ ctime }}
建立cache目录并访问
我们可以发现10s后在刷新数字才会改变!!!
[root@python newproject]# mkdir cache
http://10.10.10.111:8000/cache/
[root@python newproject]# vim app/views.py ###注释
[root@python newproject]# vim templates/cache.html
{% load cache %}
Title
{{ ctime }}
{% cache 10 c1 %}
{{ ctime }}
{% endcache %}
访问并查看结果
http://10.10.10.111:8000/cache/
[root@python newproject]# vim newproject/settings.py ###在中间件的首尾加入
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
...
'django.middleware.cache.FetchFromCacheMiddleware',
]
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 ###创建数据库连接时
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)
<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\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/
自定义信号需要开发者在任意位置触发(比如报警值超过阈值触发)!!!
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])
def callback(sender, **kwargs):
print("callback")
print(sender,kwargs)
pizza_done.connect(callback)
[root@python newproject]# vim app/views.py
from sg import pizza_done
pizza_done.send(sender="dream",toppings=123, size=456)
[root@python newproject]# vim newproject/settings.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\d+)', views.test),
path('cache/', views.cache),
path('signal/', views.signal),
path('fm/', views.fm),
]
[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/')
[root@python newproject]# vim templates/fm.html
Title
http://10.10.10.111:8000/fm/
[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/')
[root@python newproject]# vim templates/fm.html
Title
缺点:不方便自己定制!!!
[root@python newproject]# vim templates/fm.html
Title
[root@python newproject]# vim templates/fm.html
Title
[root@python newproject]# vim templates/fm.html
Title
[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/')
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类型
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
[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/')
[root@python newproject]# vim templates/fm.html
Title
{{ obj.p }}
{{ obj.province }}
{{ obj.province1 }}
[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/')
[root@python newproject]# vim templates/fm.html
Title
{{ obj.p }}
{{ obj.province }}
{{ obj.province1 }}