第八章
Posted hanwei999
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第八章相关的知识,希望对你有一定的参考价值。
- simple_tag,filter
- request
- 数据库操作
- cookie
- session
- CSRF
- 中间件
- 缓存
- 信号
- Form
1,simple_tag,filter
https://www.cnblogs.com/zhaof/p/6253130.html
2,request
request.xxx.getlist 列表 request.Meta(..) request.method(POST,GET,PUT) requet.path_info request.COOKIES a = ‘test‘ return HttpResPOnse(a) return render return redirect a = ‘test‘ response = HttpResponse(a) response[‘name‘] = ‘alex‘ response.set_cookie() return response
views
request.POST(request.body) request.FILES(request.body) request.xxx.getlist request.body request.path_info request.COOKIES request.method
3,数据库操作
models.TB.objects.get models.TB.objects.filter().update() models.TB.objects.filter().first() models.TB.objects.filter(**{}) models.TB.objects.filter(**{}).count() models.TB.objects.filter(双下划线跨表) models.TB.objects.filter(id__gt=1) models.TB.objects.filter(id__lt=1) models.TB.objects.filter(id__gte=1) models.TB.objects.filter(id__gte=1,name=‘root‘) models.TB.objects.exclude(id__gte=1) models.TB.objects.filter(id__in=[1,2,3]) 多对多: obj.set obj.add(1,2,3) obj.add([1,2,3]) obj.remove([1,2,3]) obj.clear() obj.all() models.TB.objects.all() [obj.obj] obj.fk.name models.TB.objects.all().order_by(‘‘) models.TB.objects.distinct()
4,cookie
1、获取Cookie: request.COOKIES[‘key‘] request.get_signed_cookie(key, default=RAISE_ERROR, salt=‘‘, max_age=None) 参数: default: 默认值 salt: 加密盐 max_age: 后台控制过期时间 2、设置Cookie: rep = HttpResponse(...) 或 rep = render(request, ...) rep.set_cookie(key,value,...) rep.set_signed_cookie(key,value,salt=‘加密盐‘,...) 参数: key, 键 value=‘‘, 值 max_age=None, 超时时间 expires=None, 超时时间(IE requires expires, so set it if hasn‘t been already.) path=‘/‘, Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问 domain=None, Cookie生效的域名 secure=False, https传输 httponly=False 只能http协议传输,无法被javascript获取(不是绝对,底层抓包可以获取到也可以被覆盖) 由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。 <script src=‘/static/js/jquery.cookie.js‘></script> $.cookie("list_pager_num", 30,{ path: ‘/‘ });
5,session
session通用设置
Django中默认支持Session,其内部提供了5种类型的Session供开发者使用: 数据库(默认) 缓存 文件 缓存+数据库 加密cookie 1、数据库Session Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。 a. 配置 settings.py SESSION_ENGINE = ‘django.contrib.sessions.backends.db‘ # 引擎(默认) SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认) SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认) SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认) SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认) SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认) SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认) SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认) b. 使用 def index(request): # 获取、设置、删除Session中数据 request.session[‘k1‘] request.session.get(‘k1‘,None) request.session[‘k1‘] = 123 request.session.setdefault(‘k1‘,123) # 存在则不设置 del request.session[‘k1‘] # 所有 键、值、键值对 request.session.keys() request.session.values() request.session.items() request.session.iterkeys() request.session.itervalues() request.session.iteritems() # 用户session的随机字符串 request.session.session_key # 将所有Session失效日期小于当前日期的数据删除 request.session.clear_expired() # 检查 用户session的随机字符串 在数据库中是否 request.session.exists("session_key") # 删除当前用户的所有Session数据 request.session.delete("session_key") request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。
session引擎
http://www.cnblogs.com/wupeiqi/articles/5246483.html 默认存在数据库(可以不设置) a. 配置 settings.py SESSION_ENGINE = ‘django.contrib.sessions.‘backends.db 2、缓存Session SESSION_ENGINE = ‘django.contrib.sessions.backends.cache‘ # 引擎 SESSION_CACHE_ALIAS = ‘test‘ # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置 CACHES = { ‘test‘ :{ ‘BACKEND‘:‘django.core.cache.backends.memcached.MemcachedCache‘, ‘LOCATION‘:[ ‘172.19.26.240:11211‘, 172.19.26.241:11211, ] } } 3、文件Session a. 配置 settings.py SESSION_ENGINE = ‘django.contrib.sessions.backends.file‘ # 引擎 SESSION_FILE_PATH = os.path.join(BASE_DIR,‘cache‘) 4、缓存+数据库Session a. 配置 settings.py SESSION_ENGINE = ‘django.contrib.sessions.backends.cached_db‘ # 引擎 5、加密cookie Session a. 配置 settings.py SESSION_ENGINE = ‘django.contrib.sessions.backends.signed_cookies‘ # 引擎
6,CSRF
POST提交和ajax提交 settings.py MIDDLEWARE 打开第四行 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> </head> <body> <form action="/login/" method="POST"> {% csrf_token %} <input type="text" name="user"/> <input type="password" name="pwd"/> <input type="checkbox" name="rmb" value="1"/> 5秒免登录 <input type="submit" value="提交"/> <input id="btn1" type="button" value="按钮" /> <input id="btn2" type="button" value="按钮" /> </form> <script src="/static/jquery-1.12.4.js"></script> <script src="/static/jquery.cookie.js"></script> <script> $(function(){ ###发送csrf_token $.ajaxSetup({ beforeSend: function(xhr,settings){ xhr.setRequestHeader(‘X-CSRFtoken‘, $.cookie(‘csrftoken‘)); } }); $(‘#btn1‘).click(function(){ $.ajax({ url: ‘/login/‘, type: "POST", data: {‘user‘: ‘root‘,‘pwd‘:‘123‘}, // headers: {‘X-CSRFtoken‘: $.cookie(‘csrftoken‘)}, success:function(arg){ } }) }); }) </script> </body> </html>
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> {% csrf_token %} <input type="button" onclick="Do();" value="Do it"/> <script src="/static/plugin/jquery/jquery-1.8.0.js"></script> <script src="/static/plugin/jquery/jquery.cookie.js"></script> <script type="text/javascript"> var csrftoken = $.cookie(‘csrftoken‘); function csrfSafeMethod(method) { //只有post需要发送$.cookie(‘csrftoken‘); // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } }); function Do(){ $.ajax({ url:"/app01/test/", data:{id:1}, type:‘POST‘, success:function(data){ console.log(data); } }); } </script> </body> </html>
7,中间件
指定函数使用中间件(默认全部)
跨站请求伪造 django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。 全局: 中间件 django.middleware.csrf.CsrfViewMiddleware 局部: @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。 @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。 注:from django.views.decorators.csrf import csrf_exempt,csrf_protect from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_protect def index(request): if request.session.get(‘is_login‘,None): return render(request,‘index.html‘,{‘username‘:request.session[‘username‘]}) else: return HttpResponse(‘gun‘)
中间件执行顺序
settings.py from django.middleware.csrf import CsrfViewMiddleware MIDDLEWARE = [ ‘django.middleware.security.SecurityMiddleware‘, ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, ‘django.middleware.csrf.CsrfViewMiddleware‘, ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘, ‘Middle.m1.Row1‘, ‘Middle.m1.Row2‘, ‘Middle.m1.Row3‘, ] m1.py from django.utils.deprecation import MiddlewareMixin class Row1(MiddlewareMixin): #1 def process_request(self,request): print(‘王森‘) #7 def process_view(self, request, view_func, view_func_args, view_func_kwargs): print(‘张欣彤‘) #6 def process_response(self, request, response): print(‘扛把子‘) return response from django.shortcuts import HttpResponse class Row2(MiddlewareMixin): #2 def process_request(self,request): print(‘程毅强‘) # return HttpResponse(‘走‘) # 8 def process_view(self, request, view_func, view_func_args, view_func_kwargs): print(‘张需要‘) #5 def process_response(self, request, response): print(‘侯雅凡‘) return response class Row3(MiddlewareMixin): #3 def process_request(self,request): print(‘刘东‘) #9 def process_view(self, request, view_func, view_func_args, view_func_kwargs): print(‘邵林‘) #4 def process_response(self, request, response): print(‘连之泪‘) return response def process_exception(self, request, exception): if isinstance(exception,ValueError): return HttpResponse(‘出现异常》。。‘) def process_template_response(self,request,response): # 如果Views中的函数返回的对象中,具有render方法 print(‘-----------------------‘) return response
8,缓存
由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。
Django中提供了6种缓存方式:
# 此为开始调试用,实际内部不做任何操作 # 配置: 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
1,配置
a,开发调试
开发调试 内存 文件 数据库 Memcache缓存(python-memcached模块) Memcache缓存(pylibmc模块)
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‘, } } # 注:其他配置同开发调试版本
urls.py
urlpatterns = [ url(r‘^cache/$‘,views.cache), ]
views.py
@cache_page(10) def cache(request): import time ctime = time.time() return render(request,‘cache.html‘,{‘ctime‘:ctime}) def cache(request): import time ctime = time.time() return render(request,‘cache.html‘,{‘ctime‘:ctime})
cache.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>{{ ctime }}</h1> <h1>{{ ctime }}</h1> </body> </html> ######### {% load cache %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>{{ ctime }}</h1> <h1>{{ ctime }}</h1> {% cache 10 c1 %} <h1>{{ ctime }}</h1> {% endcache %} </body> </html>
settings.py
CACHES = { ‘default‘:{ ‘BACKEND‘:‘django.core.cache.backends.filebased.FileBasedCache‘, ‘LOCATION‘: os.path.join(BASE_DIR,‘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‘, ] } } g. Redis缓存(依赖:pip3 install django-redis) CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": {"max_connections": 100} # "PASSWORD": "密码", } } } from django_redis import get_redis_connection conn = get_redis_connection("default") 2、应用 使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存 MIDDLEWARE = [ ‘django.middleware.cache.UpdateCacheMiddleware‘, # 其他中间件... ‘django.middleware.cache.FetchFromCacheMiddleware‘, ] CACHE_MIDDLEWARE_ALIAS = "" CACHE_MIDDLEWARE_SECONDS = "" CACHE_MIDDLEWARE_KEY_PREFIX = "" MIDDLEWARE = [ # ‘django.middleware.cache.UpdateCacheMiddleware‘, ‘django.middleware.security.SecurityMiddleware‘, ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, ‘django.middleware.csrf.CsrfViewMiddleware‘, ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘, # ‘Middle.m1.Row1‘, # ‘Middle.m1.Row2‘, # ‘Middle.m1.Row3‘, # ‘django.middleware.cache.FetchFromCacheMiddleware‘, ]
g. Redis缓存(依赖:pip3 install django-redis)
CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": {"max_connections": 100} # "PASSWORD": "密码", } } } from django_redis import get_redis_connection conn = get_redis_connection("default")
2,应用
使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存。
MIDDLEWARE = [ ‘django.middleware.cache.UpdateCacheMiddleware‘, # 其他中间件... ‘django.middleware.cache.FetchFromCacheMiddleware‘, ] CACHE_MIDDLEWARE_ALIAS = "" CACHE_MIDDLEWARE_SECONDS = "" CACHE_MIDDLEWARE_KEY_PREFIX = "" MIDDLEWARE = [ # ‘django.middleware.cache.UpdateCacheMiddleware‘, ‘django.middleware.security.SecurityMiddleware‘, ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, ‘django.middleware.csrf.CsrfViewMiddleware‘, ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘, # ‘Middle.m1.Row1‘, # ‘Middle.m1.Row2‘, # ‘Middle.m1.Row3‘, # ‘django.middleware.cache.FetchFromCacheMiddleware‘, ]
b. 单独视图缓存
方式一: from django.views.decorators.cache import cache_page @cache_page(60 * 15) def my_view(request): ... 方式二: from django.views.decorators.cache import cache_page urlpatterns = [ url(r‘^foo/([0-9]{1,2})/$‘, cache_page(60 * 15)(my_view)), ]
c、局部视图使用
a. 引入TemplateTag {% load cache %} b. 使用缓存 {% cache 5000 缓存key %} 缓存内容 {% endcache %}
9,信号
Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。
Model signals pre_init # django的modal执行其构造方法前,自动触发 post_init # django的modal执行其构造方法后,自动触发 pre_save # django的modal对象保存前,自动触发 post_save # django的modal对象保存后,自动触发 pre_delete # django的modal对象删除前,自动触发 post_delete # django的modal对象删除后,自动触发 m2m_changed # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发 class_prepared # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发 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内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:
###__init__.py import sg ###sp.py 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) pre_init.connect(callback) # pre_init指上述导入的内容
from django.core.signals import request_finished from django.dispatch import receiver @receiver(request_finished) def my_callback(sender, **kwargs): print("Request finished!")
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)
由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发。
url(r‘^signal/$‘, views.signal), ###__init__.py import sg ###sp.py def signal(reuqest): from app01 import models obj = models.UserInf(user=‘root‘) print(‘end‘) obj.save() obj = models.UserInf(user=‘root‘) obj.save() obj = models.UserInf(user=‘root‘) obj.save() 触发 from sg import pizza_done pizza_done.send(sender="asdfasdf",toppings=123, size=456) return HttpResponse(‘ok‘) ###sg.py 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 自定义信号 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) http://www.cnblogs.com/wupeiqi/articles/5246483.html
10,Form
url(r‘^fm/$‘,views.fm), from django import forms from django.forms import widgets from django.forms import fields class FM(forms.Form): # 字段本身只做验证 #自定义字段 user = fields.CharField( error_messages={‘required‘: ‘用户名不能为空.‘}, #自定义插件 widget=widgets.Textarea(attrs={‘class‘: ‘c1‘}), label=‘用户名‘, ) pwd = fields.CharField( max_length=12, min_length=6, error_messages={‘required‘:‘密码不能为空.‘,‘min_length‘:‘密码长度不能小于6‘,‘max_length‘:‘密码长度不能大于12‘}, widget=widgets.PasswordInput(attrs={‘class‘: ‘c2‘}) ) email = fields.EmailField(error_messages={‘required‘:‘邮箱不能为空‘,‘invalid‘:‘邮箱格式错误‘}) #上传文件 f = fields.FileField() # p = fields.FilePathField(path=‘app01‘) city1 = fields.ChoiceField( choices=[(0,‘上海‘),(1,‘广州‘),(2,‘东莞‘)] ) city2 = fields.MultipleChoiceField( choices=[(0,‘上海‘),(1,‘广州‘),(2,‘东莞‘)] ) from app01 import models def fm(request): if request.method == "GET": # 从数据库中把数据获取到 dic = { "user": ‘r1‘, ‘pwd‘: ‘123123‘, ‘email‘: ‘sdfsd‘, ‘city1‘:1, ‘city2‘:[1,2] } obj = FM(initial=dic) return render(request,‘fm.html‘,{‘obj‘:obj}) elif request.method == "POST": # 获取用户所有数据 # 每条数据请求的验证 # 成功 获取所有的正确的信息 # 失败 显示错误信息 obj = FM(request.POST) r1 = obj.js_valid() if r1: # obj.cleaned_data models.UserInf.objects.create(**obj.cleaned_data) else: # ErrorDict # print(obj.errors.as_json()) # print(obj.errors[‘user‘][0]) return render(request,‘fm.html‘,{‘obj‘:obj}) return render(request,‘fm.html‘)
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.label }} {{ obj.user }} {{ obj.errors.user.0 }}</p> <p>{{ obj.pwd }} {{ obj.errors.pwd.0 }}</p> <p>{{ obj.email }} {{ obj.errors.email.0 }}</p> <p>{{ obj.f }} {{ obj.errors.f.0 }}</p> {{ obj.city1 }} {{ obj.city2 }} <input type="submit" value="提交"/> </form> </body> </html>
创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;
1、Django内置字段如下:
Field required=True, 是否允许为空 widget=None, HTML插件 label=None, 用于生成Label标签或显示内容 initial=None, 初始值 help_text=‘‘, 帮助信息(在标签旁边显示) error_messages=None, 错误信息 {‘required‘: ‘不能为空‘, ‘invalid‘: ‘格式错误‘} show_hidden_initial=False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直) 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) 格式:2015-09-01 TimeField(BaseTemporalField) 格式:11:12 DateTimeField(BaseTemporalField)格式:2015-09-01 11: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类型
注: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‘x00x01x02x03x04x05x06x07x08 x0bx0c x0ex0f‘ # make a UUID from a 16-byte string >>> uuid.UUID(bytes=x.bytes) UUID(‘00010203-0405-0607-0809-0a0b0c0d0e0f‘)
2、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
常用插件
单radio,值为字符串 user = fields.CharField( initial=2, widget=widgets.RadioSelect(choices=((1,‘上海‘),(2,‘北京‘),)) ) 单radio,值为字符串 user = fields.ChoiceField( choices=((1, ‘上海‘), (2, ‘北京‘),), initial=2, widget=widgets.RadioSelect ) 单select,值为字符串 user = fields.CharField( initial=2, widget=widgets.Select(choices=((1,‘上海‘),(2,‘北京‘),)) ) 单select,值为字符串 user = fields.ChoiceField( choices=((1, ‘上海‘), (2, ‘北京‘),), initial=2, widget=widgets.Select ) 多选select,值为列表 user = fields.MultipleChoiceField( choices=((1,‘上海‘),(2,‘北京‘),), initial=[1,], widget=widgets.SelectMultiple ) 单checkbox user = fields.CharField( widget=widgets.CheckboxInput() ) 多选checkbox,值为列表 user = fields.MultipleChoiceField( initial=[2, ], choices=((1, ‘上海‘), (2, ‘北京‘),), widget=widgets.CheckboxSelectMultiple )
自定义验证规则
方式一:
from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator class MyForm(Form): user = fields.CharField( validators=[RegexValidator(r‘^[0-9]+$‘, ‘请输入数字‘), RegexValidator(r‘^159[0-9]+$‘, ‘数字必须以159开头‘)], )
方式二:
import re from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.exceptions import ValidationError # 自定义验证规则 def mobile_validate(value): mobile_re = re.compile(r‘^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$‘) if not mobile_re.match(value): raise ValidationError(‘手机号码格式错误‘) class PublishForm(Form): title = fields.CharField(max_length=20, min_length=5, error_messages={‘required‘: ‘标题不能为空‘, ‘min_length‘: ‘标题最少为5个字符‘, ‘max_length‘: ‘标题最多为20个字符‘}, widget=widgets.TextInput(attrs={‘class‘: "form-control", ‘placeholder‘: ‘标题5-20个字符‘})) # 使用自定义验证规则 phone = fields.CharField(validators=[mobile_validate, ], error_messages={‘required‘: ‘手机不能为空‘}, widget=widgets.TextInput(attrs={‘class‘: "form-control", ‘placeholder‘: u‘手机号码‘})) email = fields.EmailField(required=False, error_messages={‘required‘: u‘邮箱不能为空‘,‘invalid‘: u‘邮箱格式错误‘}, widget=widgets.TextInput(attrs={‘class‘: "form-control", ‘placeholder‘: u‘邮箱‘}))
方法三:自定义方法
from django import forms from django.forms import fields from django.forms import widgets from django.core.exceptions import ValidationError from django.core.validators import RegexValidator class FInfo(forms.Form): username = fields.CharField(max_length=5, validators=[RegexValidator(r‘^[0-9]+$‘, ‘Enter a valid extension.‘, ‘invalid‘)], ) email = fields.EmailField() def clean_username(self): """ Form中字段中定义的格式匹配完之后,执行此方法进行验证 :return: """ value = self.cleaned_data[‘username‘] if "666" in value: raise ValidationError(‘666已经被玩烂了...‘, ‘invalid‘) return value
方式四:同时生成多个标签进行验证
from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator ############## 自定义字段 ############## class PhoneField(fields.MultiValueField): def __init__(self, *args, **kwargs): # Define one message for all fields. error_messages = { ‘incomplete‘: ‘Enter a country calling code and a phone number.‘, } # Or define a different message for each field. f = ( fields.CharField( error_messages={‘incomplete‘: ‘Enter a country calling code.‘}, validators=[ RegexValidator(r‘^[0-9]+$‘, ‘Enter a valid country calling code.‘), ], ), fields.CharField( error_messages={‘incomplete‘: ‘Enter a phone number.‘}, validators=[RegexValidator(r‘^[0-9]+$‘, ‘Enter a valid phone number.‘)], ), fields.CharField( validators=[RegexValidator(r‘^[0-9]+$‘, ‘Enter a valid extension.‘)], required=False, ), ) super(PhoneField, self).__init__(error_messages=error_messages, fields=f, require_all_fields=False, *args, **kwargs) def compress(self, data_list): """ 当用户验证都通过后,该值返回给用户 :param data_list: :return: """ return data_list ############## 自定义插件 ############## class SplitPhoneWidget(widgets.MultiWidget): def __init__(self): ws = ( widgets.TextInput(), widgets.TextInput(), widgets.TextInput(), ) super(SplitPhoneWidget, self).__init__(ws) def decompress(self, value): """ 处理初始值,当初始值initial不是列表时,调用该方法 :param value: :return: """ if value: return value.split(‘,‘) return [None, None, None] 初始化数据 http://www.cnblogs.com/wupeiqi/articles/6144178.html
初始化
在Web应用程序中开发编写功能时,时常用到获取数据库中的数据并将值初始化在HTML中的标签上。
1、Form
from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator class MyForm(Form): user = fields.CharField() city = fields.ChoiceField( choices=((1, ‘上海‘), (2, ‘北京‘),), widget=widgets.Select )
2、Views
from django.shortcuts import render, redirect from .forms import MyForm def index(request): if request.method == "GET": values = {‘user‘: ‘root‘, ‘city‘: 2} obj = MyForm(values) return render(request, ‘index.html‘, {‘form‘: obj}) elif request.method == "POST": return redirect(‘http://www.google.com‘) else: 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>
以上是关于第八章的主要内容,如果未能解决你的问题,请参考以下文章