一、Form表单验证
用于做用户提交数据的验证
1.自定义规则
a、自定义规则(类,字段名==html中的name值)
b、数据提交-规则进行匹配
代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
"""day19_django URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.10/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.login), ]
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
""" Django settings for day19_django project. Generated by 'django-admin startproject' using Django 1.10.2. For more information on this file, see https://docs.djangoproject.com/en/1.10/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.10/ref/settings/ """ import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'pv#lfw8ywtf=ws8mr%f9b)ihc0s@oj-2$wu^2o@)+(^)$i_9*n' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', ] 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', ] ROOT_URLCONF = 'day19_django.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'day19_django.wsgi.application' # Database # https://docs.djangoproject.com/en/1.10/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # Password validation # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/1.10/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.10/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), )
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
from django.shortcuts import render,HttpResponse from django import forms from django.forms.utils import ErrorDict import json from django.core.exceptions import ValidationError import re def mobile_validate(value): mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') if not mobile_re.match(value): raise ValidationError('手机号码格式错误') class LoginForm(forms.Form): user = forms.CharField(required=True, error_messages={'required':'用户名不能为空'}) pwd = forms.CharField(required=True, min_length=6, max_length=12, error_messages={'required':'密码必须不能为空', 'min_length':'至少6位', 'max_length':'最多12位'}) num = forms.IntegerField(error_messages={'required':'数字不能为空', 'invalid':'必须输入数字'}) #url = forms.EmailField() phone = forms.CharField(validators=[mobile_validate, ],) def login(request): if request.method == 'POST': result = {'status':False, 'message':None} obj = LoginForm(request.POST) ret = obj.is_valid() if ret: print(obj.clean()) result['status'] = True else: print(type(obj.errors), obj.errors.as_json()) error_str = obj.errors.as_json() result['message'] = json.loads(error_str) return HttpResponse(json.dumps(result)) return render(request, 'login.html')
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .error-msg{ background-color: red; } </style> </head> <body> <div> <div> <input type="text" name="user" /> </div> <div> <input type="text" name="num" /> </div> <div> <input type="text" name="phone" /> </div> <div> <input type="password" name="pwd" /> </div> <input type="button" value="提交" οnclick="DoSubmit();" /> </div> <script src="/static/jquery-1.12.4.js"></script> <script> function DoSubmit() { var dict_input = {}; $('input').each(function () { var v = $(this).val(); var n = $(this).attr('name'); dict_input[n] = v; }); console.log(dict_input); $('.error-msg').remove(); $.ajax({ url:'/login/', type:'POST', data:dict_input, dataType: 'json', success:function (result) { if(result.status){ location.href = '/index/'; }else{ $.each(result.message, function (k, v) { console.log(k, v[0].message); //<sapn class="error-msg">错误信息</span> var tag = document.createElement('span'); tag.className = 'error-msg'; tag.innerText = v[0].message; //input[name="user"] $('input[name="' + k + '"]').after(tag); }) } }, error:function () { } }) } </script> </body> </html>
2.用于做用户提交数据的验证 + 生成HTML标签
代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
from django.shortcuts import render,HttpResponse from django import forms from django.forms.utils import ErrorDict import json from django.core.exceptions import ValidationError import re def mobile_validate(value): mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') if not mobile_re.match(value): raise ValidationError('手机号码格式错误') class LoginForm(forms.Form): user = forms.CharField(required=True, error_messages={'required':'用户名不能为空'}) pwd = forms.CharField(required=True, min_length=6, max_length=12, error_messages={'required':'密码必须不能为空', 'min_length':'至少6位', 'max_length':'最多12位'}) num = forms.IntegerField(error_messages={'required':'数字不能为空', 'invalid':'必须输入数字'}) #url = forms.EmailField() phone = forms.CharField(validators=[mobile_validate, ],) #生成input标签,并加属性,设置样式 #test = forms.CharField(widget=forms.TextInput(attrs={'k1':'123','class':'error-msg'})) #生成下拉列表,真正提交数据还是数字 test_choices = { (0, '上海'), (1, '北京'), } test = forms.IntegerField(widget=forms.Select(choices=test_choices)) def login(request): if request.POST: objPost = LoginForm(request.POST) ret = objPost.is_valid() if ret: print(objPost.clean()) else: #obj1.errors是ErrorDict,ErrorDict继承dict # for k,v in objPost.errors.items(): # print(k, v) # print(objPost.errors['phone'][0]) # print(objPost.errors['user'][0]) # print(objPost.errors['num'][0]) pass return render(request, 'login.html', {'obj1': objPost}) else: objGet = LoginForm() return render(request, 'login.html', {'obj1':objGet})
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .error-msg{ background-color: red; } </style> </head> <body> <form action="/login/" method="POST"> <div> <div> {{ obj1.user }} {% if obj1.errors.user %} <span class="error-msg">{{ obj1.errors.user.0 }}</span> {% endif %} </div> <div> {{ obj1.pwd }} {% if obj1.errors.pwd %} <span class="error-msg">{{ obj1.errors.pwd.0 }}</span> {% endif %} </div> <div> {{ obj1.num }} {% if obj1.errors.num %} <span class="error-msg">{{ obj1.errors.num.0 }}</span> {% endif %} </div> <div> {{ obj1.phone }} {% if obj1.errors.phone %} <span class="error-msg">{{ obj1.errors.phone.0 }}</span> {% endif %} </div> <div> {{ obj1.test }} </div> <input type="submit" value="提交" /> </div> </form> </body> </html>
二、CSRF
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
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
"""day19_django URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.10/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.login), url(r'^csrf/', views.csrf), ]
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
from django.shortcuts import render,HttpResponse from django import forms from django.forms.utils import ErrorDict import json from django.core.exceptions import ValidationError import re def mobile_validate(value): mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') if not mobile_re.match(value): raise ValidationError('手机号码格式错误') class LoginForm(forms.Form): user = forms.CharField(required=True, error_messages={'required':'用户名不能为空'}) pwd = forms.CharField(required=True, min_length=6, max_length=12, error_messages={'required':'密码必须不能为空', 'min_length':'至少6位', 'max_length':'最多12位'}) num = forms.IntegerField(error_messages={'required':'数字不能为空', 'invalid':'必须输入数字'}) #url = forms.EmailField() phone = forms.CharField(validators=[mobile_validate, ],) #生成input标签,并加属性,设置样式 #test = forms.CharField(widget=forms.TextInput(attrs={'k1':'123','class':'error-msg'})) #生成下拉列表,真正提交数据还是数字 test_choices = { (0, '上海'), (1, '北京'), } test = forms.IntegerField(widget=forms.Select(choices=test_choices)) def login(request): if request.POST: objPost = LoginForm(request.POST) ret = objPost.is_valid() if ret: print(objPost.clean()) else: #obj1.errors是ErrorDict,ErrorDict继承dict # for k,v in objPost.errors.items(): # print(k, v) # print(objPost.errors['phone'][0]) # print(objPost.errors['user'][0]) # print(objPost.errors['num'][0]) pass return render(request, 'login.html', {'obj1': objPost}) else: objGet = LoginForm() return render(request, 'login.html', {'obj1':objGet}) def csrf(request): return render(request, 'csrf.html')
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--form提交--> <form action="/csrf/" method="POST"> {% csrf_token %} <input type="text" name="v" /> <input type="submit" value="提交" /> </form> <input type="button" value="Ajax提交" οnclick="DoAjax();" /> <!--ajax提交--> <script src="/static/jquery-2.1.4.min.js"></script> <script src="/static/jquery.cookie.js"></script> <script> //获取cookie var csrftoken = $.cookie('csrftoken'); function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } }); function DoAjax() { $.ajax({ url:'/csrf/', type:'POST', data:{'k1':'v1'}, success: function (data) { console.log(data); } }) } </script> </body> </html>
三、Cookie和Session
Cookie保存在客户端浏览器上的一个容器,独立存在
服务器上保存的是session(内存或数据库或缓存),依赖Cookie
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
"""day19_django URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.10/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.login), url(r'^csrf/', views.csrf), url(r'^cookie/', views.cookie), url(r'^cookie1/', views.cookie), url(r'^log/', views.log), url(r'^index/', views.index), url(r'^session_login/', views.session_login), url(r'^session_index/', views.session_index), url(r'^session_logout/', views.session_logout), ]
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
from django.shortcuts import render,HttpResponse,redirect from django import forms from django.forms.utils import ErrorDict import json from django.core.exceptions import ValidationError import re from django.views.decorators.csrf import csrf_exempt,csrf_protect 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 LoginForm(forms.Form): user = forms.CharField(required=True, error_messages={'required':'用户名不能为空'}) pwd = forms.CharField(required=True, min_length=6, max_length=12, error_messages={'required':'密码必须不能为空', 'min_length':'至少6位', 'max_length':'最多12位'}) num = forms.IntegerField(error_messages={'required':'数字不能为空', 'invalid':'必须输入数字'}) #url = forms.EmailField() phone = forms.CharField(validators=[mobile_validate, ],) #生成input标签,并加属性,设置样式 #test = forms.CharField(widget=forms.TextInput(attrs={'k1':'123','class':'error-msg'})) #生成下拉列表,真正提交数据还是数字 test_choices = { (0, '上海'), (1, '北京'), } test = forms.IntegerField(widget=forms.Select(choices=test_choices)) def login(request): if request.POST: objPost = LoginForm(request.POST) ret = objPost.is_valid() if ret: print(objPost.clean()) else: #obj1.errors是ErrorDict,ErrorDict继承dict # for k,v in objPost.errors.items(): # print(k, v) # print(objPost.errors['phone'][0]) # print(objPost.errors['user'][0]) # print(objPost.errors['num'][0]) pass return render(request, 'login.html', {'obj1': objPost}) else: objGet = LoginForm() return render(request, 'login.html', {'obj1':objGet}) #@csrf_protect 强制给函数加csrf验证 @csrf_exempt #不用做csrf验证 def csrf(request): return render(request, 'csrf.html') #使用Cookie做登录认证 def cookie(request): print(request.COOKIES) obj = render(request, 'cookie.html') #path='/cookie/',Cookie存放路径 obj.set_cookie('k3','v3',path='/cookie/') return obj def cookie1(request): print(request.COOKIES) obj = render(request, 'cookie.html') #path='/',Cookie全局生效 obj.set_cookie('k1','v1',path='/') return obj def log(request): if request.method == 'POST': u = request.POST.get('user') p = request.POST.get('pwd') if u == 'alex' and p == '123': print(u) red = redirect('/index/') red.set_cookie('username', u) return red else: return render(request, 'log.html') else: return render(request, 'log.html') def index(request): user = request.COOKIES.get('username') if user: return render(request, 'index.html', {'user':user}) else: return redirect('/log/') #使用session做登录认证 USER_LIST = ['alex','eric','wang','liu'] def session_login(request): if request.method == 'POST': u = request.POST.get('user') p = request.POST.get('pwd') if u in USER_LIST and p == '123': request.session['user'] = u return redirect('/session_index/') return render(request, 'session_login.html') """ def session_index(request): user = request.session.get('user', None) if not user: return redirect('/session_login/') else: return render(request, 'session_index.html', {'user':user}) """ def auth(func): def inner(request, *args, **kwargs): #print(request, args, kwargs) user = request.session.get('user', None) if not user: return redirect('/session_login/') return func(request, *args, **kwargs) return inner @auth def session_index(request): user = request.session.get('user', None) return render(request, 'session_index.html', {'user':user}) @auth def session_logout(request): del request.session['user'] return redirect('/session_login/')
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <form action="/session_login/" method="POST"> <input type="text" name="user"> <input type="text" name="pwd"> <input type="submit" value="提交" /> </form> </body> </html>
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <form action="/session_login/" method="POST"> <input type="text" name="user"> <input type="text" name="pwd"> <input type="submit" value="提交" /> </form> </body> </html>
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <form action="/log/" method="POST"> <input type="text" name="user"> <input type="text" name="pwd"> <input type="submit" value="提交" /> </form> </body> </html>
四、Model操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
a.基本 b.进阶 c.双下划线 __大于小于操作 __可以跨表 class UserInfo(models.Model): user = models.CharField(max_length=32) pwd = models.CharField(max_length=32) queryset = UserInfo.objects.all() print(queryset.query) --SQL语句 [UserInfo对象,UserInfo对象,UserInfo对象,] queryset = UserInfo.objects.all().values('user') [{'user':'alex'},{'user':'eric'}] queryset = UserInfo.objects.all().value_list('user') [('alex'),('eric')] ======================================================= 一对多 class UserType(models.Model): caption = models.CharField(max_length=32) #超级管理员、普通用户、访客、黑客 class UserInfo(models.Model): user = models.CharField(max_length=32) pwd = models.CharField(max_length=32) user_type = models.ForeignKey('UserType') #user_type_id #创建UserInfo 1、UserInfo.objects.create(user='alex',pwd='123',user_type=UserType.objects.get(id=2)) 或: 2、UserInfo.objects.create(user='alex',pwd='123',user_type_id=2) #查询 UserInfo.objects.filter(user='alex') 1、查询所有用户类型为普通用户的所有用户名和密码 uid = UserType.objects.get(caption='普通用户').id UserInfo.objects.filter(user_type_id=uid) 或: queryset = UserInfo.objects.filter(user_type__caption='普通用户') -- 跨表使用双下划线 [UserInfo对象,UserInfo对象,UserInfo对象,] row = queryset[0] row.user row.pwd row.user_type -- user_type对象 row.user_type.id row.user_type.caption ###### objects __ ###### row.外键字段.外键表的字段 queryset = UserInfo.objects.filter(user_type__caption='普通用户').values('user', 'user_type__caption') -- 跨表使用双下划线 [{'user':'alex','user_type__caption':'普通用户'},{'user':'eric','user_type__caption':'普通用户'}] row = queryset[0] row['user'] row['user_type__caption'] 多张表 class Something(models.Model): name = models.CharField(max_length=32) class UserType(models.Model): caption = models.CharField(max_length=32) st = models.ForeignKey('Something') #超级管理员、普通用户、访客、黑客 class UserInfo(models.Model): user = models.CharField(max_length=32) pwd = models.CharField(max_length=32) user_type = models.ForeignKey('UserType') #user_type_id UserInfo.objects.filter(user_type__st__name='xx')