Form
django中的Form一般有两种功能:
1、输入html
2、验证用户输入
最简易的form验证:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .inline-group{ position: relative; padding: 5px; width: 250px; } .input-group input{ width: 200px; display: inline-block; } .inline-group span{ display: inline-block; position: absolute; height: 12px; font-size: 8px; border: 1px solid darkorchid; background-color: chartreuse; color: aliceblue; top: 41px; left: 20px; width: 202px; } </style> </head> <body> <form action="form1/" method="POST"> <div class="inline-group"> {{ form.user }} {#创建user的input标签#} {% if error.user.0 %} {#如果出错误就把错误信息显示出来,否则隐藏#} <span>{{ error.user.0 }}</span> {# 获得错误信息#} {% endif %} </div> <div class="inline-group"> {{ form.pwd }} {# 创建pwd的input标签#} {% if error.pwd.0 %} <span>{{ error.pwd.0 }}</span> {% endif %} </div> <div > <input type="submit" value="提交"/> </div> </form> </body> </html>
# !/usr/bin/env python # -*- coding:utf-8 -*- from django.shortcuts import render from app01.forms import Form1 from django.forms.utils import ErrorDict def form1(request): if request.method == 'POST': # 判断是否是通过POST方法获取 # request.POST.get('user', None) # request.POST.get('pwd', None) # 获取请求内容,做验证 f = Form1(request.POST) if f.is_valid(): print(f.cleaned_data) else: print(type(f.errors), f.errors) return render(request, 'account/form1.html', {'error': f.errors}) # {'error': f.errors}错误信息 else: f = Form1() return render(request, 'account/form1.html', {'form': f})
上面的只是实现最简易的form验证,更没法在生产环境下运用;要想在生产环境下运用就需要我们根据业务需求自定制form验证。
下面我们来写一个比较差不多的自定制的form验证。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .input-group{ position: relative; padding: 5px; width: 250px; } .input-group input{ width: 200px; display: inline-block; } .input-group span{ display: inline-block; position: absolute; height: 12px; font-size: 8px; border: 1px solid darkred; background-color: coral; color: white; top: 41px; left: 20px; width: 202px; } </style> </head> <body> <form action="/form1/" method="POST"> <div class="input-group"> {{ form.user }} {% if error.user.0 %} <span>{{ error.user.0 }}</span> {% endif %} </div> <div class="input-group"> {{ form.pwd }} {% if error.pwd.0 %} <span>{{ error.pwd.0 }}</span> {% endif %} </div> <div class="input-group"> {{ form.email }} {% if error.email.0 %} <span>{{ error.email.0 }}</span> {% endif %} </div> <div class="input-group"> {{ form.memo }} {% if error.memo.0 %} <span>{{ error.memo.0 }}</span> {% endif %} </div> <div class="input-group"> {{ form.book_type }} {% if error.book_type.0 %} <span>{{ error.book_type.0 }}</span> {% endif %} </div> <div> <input type="submit" value="提交"/> </div> </form> </body> </html>
#!/usr/bin/env python # -*- coding:utf-8 -*- from django import forms from app01 import models class Form1(forms.Form): user = forms.CharField( widget=forms.TextInput(attrs={'class': 'c1'}), # attrs参数给标签加样式(添加样式) error_messages={'required': '用户名不能为空'},) # error_messages为自定义错误信息(定制错误信息) pwd = forms.CharField(max_length=4,min_length=2) # 参数是最多4个,最少两个(定义字符长短) email = forms.EmailField(error_messages={'required': '邮箱不能为空', 'invalid': '邮箱格式错误'}) # # required表示不能为空的错误提示,invalid格式错误提示 memo = forms.CharField( widget=forms.Textarea() # 生成Textarea标签 ) # user_type_choice = ( # (0, '普通用户'), # (1, '高级用户'), # ) user_type_choice = models.BookType.objects.values_list('id','caption') # 也可以通过映射values_list,弄一个字典在数据库取相应的下拉选项内容 book_type = forms.CharField( # 下拉框选项(下拉选项可以在上面定义好) widget=forms.widgets.Select(choices=user_type_choice,attrs={'class': "form-control"})) def __init__(self,*args, **kwargs): # 创建Init方法在每次创建对象的时候再执行一次,检查下数据库是否修改过 super(Form1, self).__init__(*args, **kwargs) self.fields['book_type'] = forms.CharField( # 在数据库查看是否修改过,并拿值。 widget=forms.widgets.Select(choices=models.BookType.objects.values_list('id','caption'),attrs={'class': "form-control"}))
扩展:ModelForm
在使用Model和Form时,都需要对字段进行定义并指定类型,通过ModelForm则可以省去From中字段的定义
class AdminModelForm(forms.ModelForm): class Meta: model = models.Admin #fields = '__all__' fields = ('username', 'email') widgets = { 'email' : forms.PasswordInput(attrs={'class':"alex"}), }
上面都是简单的整体的整理下form验证,这不是Form的全部,下面我在重新过一遍相对比较全些的Form。
1、输入html
from django.shortcuts import render from django import forms class UserForm(forms.Form): host = forms.CharField() port = forms.CharField() email = forms.EmailField() mobile = forms.CharField() def user_list(request): obj = UserForm() return render(request,"index.html",{"obj":obj})
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/app01/user_list/"> <!--自动生成input标签--> <p>主机:{{ obj.host }}</p> <p>端口:{{ obj.port }}</p> <p>邮箱:{{ obj.email }}</p> <p>手机:{{ obj.mobile }}</p> <input type="submit"> </form> </body> </html>
2、验证
from django.shortcuts import render from django import forms class UserForm(forms.Form): host = forms.CharField() port = forms.CharField() email = forms.EmailField() mobile = forms.CharField() def user_list(request): obj = UserForm() if request.method == "POST": # 判断是否post方式 user_input_obj = UserForm(request.POST) # 把提交过来的数据封装到UserForm,UserForm会自动把数据封装到user_input_obj if user_input_obj.is_valid(): # 验证用户输入是否合法 data = user_input_obj.clean() # 合法,获取数据 else: error_msg = user_input_obj.errors # 不合法,返回错误信息 return render(request,"index.html",{"obj":user_input_obj,"error":error_msg}) return render(request,"index.html",{"obj":obj})
优化
def user_list(request): obj = UserForm(request.POST) # 如果有数据,把提交过来的数据封装到UserForm,UserForm会自动把数据封装到user_input_obj if request.method == "POST": if obj.is_valid(): # 验证用户输入是否合法 data = obj.clean() # 合法,获取数据 else: error_msg = obj.errors.as_data() # 不合法,返回错误信息 return render(request,"index.html",{"obj":obj,"error":error_msg}) return render(request,"index.html",{"obj":obj,})
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/app01/user_list/" method="post"> <!--自动生成input标签--> <p>主机:{{ obj.host }}<span>{{ error.host }}</span></p> <p>端口:{{ obj.port }}<span>{{ error.port }}</span></p> <p>邮箱:{{ obj.email }}<span>{{ error.email }}</span></p> <p>手机:{{ obj.mobile }}<span>{{ error.mobile }}</span></p> <input type="submit"> </form> </body> </html>
3、定制From表单
(1)设置报错信息,添加属性样式
class UserForm(forms.Form): host = forms.CharField(error_messages={"required":"主机不能为空"},#设置显示的错误信息 widget=forms.TextInput(attrs={"class":"form-control", "placeholder": "主机"})#添加属性和样式 ) port = forms.CharField() email = forms.EmailField() mobile = forms.CharField()
(2)多行文本框
#多行文本框,备注 memo = forms.CharField(required=False, #可以为空 widget=forms.Textarea(attrs={"class":"form-control", "placeholder": "备注"})#添加属性和样式 )
(3)下拉框
#下拉框 user_type_choice=( (0,"普通用户"), (1,"高级用户") ) user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice, attrs={'class': "form-control"}))
(4)动态生成select标签
文件中取数据
#动态下拉框 u_type = forms.IntegerField(widget=forms.widgets.Select( attrs={'class': "form-control"})) def __init__(self, *args, **kwargs): super(UserForm, self).__init__(*args, **kwargs) import json f=open("u_type_db") data = f.read() data_tuple = json.loads(data) self.fields['u_type'].widget.choices = data_tuple
user_type_choice = ( (0, "普通用户"), (1, "高级用户") )
数据库中取数据
最开始的form就是数据库中去数据,而且在数据库修改时,下拉框的内容不需要刷新页面也可以生成。
def __init__(self, *args, **kwargs): super(UserForm, self).__init__(*args, **kwargs) data_tuple=models.UserInfo.objects.all().values_list('id','username') self.fields['u_type'].widget.choices = data_tuple
(5)自定义验证条件
#自定义验证 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 UserForm(forms.Form): mobile = forms.CharField(validators=[mobile_validate, ])#添加自定义手机号验证
4、美化显示错误信息
def user_list(request): obj = UserForm() if request.method == "POST": user_input_obj = UserForm(request.POST)#把提交过来的数据封装到UserForm,UserForm会自动把数据封装到user_input_obj if user_input_obj.is_valid(): #验证用户输入是否合法 data = user_input_obj.clean() #合法,获取数据 else: error_msg = user_input_obj.errors #不合法,返回错误信息 return render(request,"index.html",{"obj":user_input_obj,"error":error_msg}) return render(request,"index.html",{"obj":obj,})
默认显示ul样式,不美观
error_msg = user_input_obj.errors #不合法,返回错误信息
改成as_data()后只显示一个字符串格式
error_msg = user_input_obj.errors.as_data() #不合法,返回错误信息
修改方法:
1、定义
2、在html顶部调用
{% load form_tag %}
3、引用
<p>主机:{{ obj.host }}<span>{% error_message error.host %}</span></p>
as_json()用于ajax返回
error_msg = user_input_obj.errors.as_json()#不合法,返回错误信息 return HttpResponse(error_msg )
实例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/app01/user_list/"> <!--自动生成input标签--> {# <p>主机:{{ obj.host }}</p>#} {# <p>端口:{{ obj.port }}</p>#} {# <p>邮箱:{{ obj.email }}</p>#} {# <p>手机:{{ obj.mobile }}</p>#} {# <input type="submit">#} {# 进一步优化#} <p>主机:{{ obj.host }}<span>{{ error.host }}</span></p> <p>端口:{{ obj.port }}<span>{{ error.port }}</span></p> <p>邮箱:{{ obj.email }}<span>{{ error.email }}</span></p> <p>手机:{{ obj.mobile }}<span>{{ error.mobile }}</span></p> <p>备注:{{ obj.memo }}<span>{{ error.memo }}</span></p> <p>用户类型:{{ obj.user_type }}<span>{{ error.user_type }}</span></p> <input type="submit"> </form> </body> </html>
from django.shortcuts import render
from django import forms
import re
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 UserForm(forms.Form):
host = forms.CharField(error_messages={"required": "主机不能为空"}, # 设置显示的错误信息
widget=forms.TextInput(attrs={"class": "form-control",
"placeholder": "主机"}) # 添加属性和样式
)
port = forms.CharField(error_messages={"required": "端口不能为空"},
widget=forms.TextInput(attrs={"class": "form-control",
"placeholder": "端口"})
)
email = forms.EmailField(error_messages={"required": "邮箱不能为空"},
widget=forms.TextInput(attrs={"class": "form-control",
"placeholder": "邮箱"})
)
mobile = forms.CharField(error_messages={"required": "手机不能为空"},
widget=forms.TextInput(attrs={"class": "form-control",
"placeholder": "手机"}),
validators=[mobile_validate]) # 添加自定义验证
# 多行文本框,备注
memo = forms.CharField(required=False, # 可以为空
widget=forms.Textarea(attrs={"class": "form-control",
"placeholder": "备注"}) # 添加属性和样式
)
# 下拉框
user_type_choice = (
(0, "普通用户"),
(1, "高级用户")
)
user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
attrs={'class': "form-control"}))
def user_list(request):
obj = UserForm()
if request.method == "POST":
user_input_obj = UserForm(request.POST) # 把提交过来的数据封装到UserForm,UserForm会自动把数据封装到user_input_obj
if user_input_obj.is_valid(): # 验证用户输入是否合法
data = user_input_obj.clean() # 合法,获取数据
print(data)
else:
error_msg = user_input_obj.errors.as_data() # 不合法,返回错误信息
return render(request, "index.html", {"obj": user_input_obj, "error": error_msg})
return render(request, "index.html", {"obj": obj})
5、分页
一、Django内置分页
Paginator
二、自定义分页
分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。
1、设定每页显示数据条数
2、用户输入页码(第一页、第二页...)
3、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置
4、在数据表中根据起始位置取值,页面上输出数据
需求又来了,需要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]
1、设定每页显示数据条数
2、用户输入页码(第一页、第二页...)
3、设定显示多少页号
4、获取当前数据总条数
5、根据设定显示多少页号和数据总条数计算出,总页数
6、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置
7、在数据表中根据起始位置取值,页面上输出数据
8、输出分页html,如:[上一页][1][2][3][4][5][下一页]
#!/usr/bin/env python # _*_coding:utf-8_*_ from django.utils.safestring import mark_safe class PageInfo(object): def __init__(self,current,totalItem,peritems=5): self.__current=current self.__peritems=peritems self.__totalItem=totalItem def From(self): return (self.__current-1)*self.__peritems def To(self): return self.__current*self.__peritems def TotalPage(self): #总页数 result=divmod(self.__totalItem,self.__peritems) if result[1]==0: return result[0] else: return result[0]+1 def Custompager(baseurl,currentPage,totalpage): #基础页,当前页,总页数 perPager=11 #总页数<11 #0 -- totalpage #总页数>11 #当前页大于5 currentPage-5 -- currentPage+5 #currentPage+5是否超过总页数,超过总页数,end就是总页数 #当前页小于5 0 -- 11 begin=0 end=0 if totalpage <= 11: begin=0 end=totalpage else: if currentPage>5: begin=currentPage-5 end=currentPage+5 if end > totalpage: end=totalpage else: begin=0 end=11 pager_list=[] if currentPage<=1: first="<a href=''>首页</a>" else: first="<a href='%s%d'>首页</a>" % (baseurl,1) pager_list.append(first) if currentPage<=1: prev="<a href=''>上一页</a>" else: prev="<a href='%s%d'>上一页</a>" % (baseurl,currentPage-1) pager_list.append(prev) for i in range(begin+1,end+1): if i == currentPage: temp="<a href='%s%d' class='selected'>%d</a>" % (baseurl,i,i) else: temp="<a href='%s%d'>%d</a>" % (baseurl,i,i) pager_list.append(temp) if currentPage>=totalpage: next="<a href='#'>下一页</a>" else: next="<a href='%s%d'>下一页</a>" % (baseurl,currentPage+1) pager_list.append(next) if currentPage>=totalpage: last="<a href=''>末页</a>" else: last="<a href='%s%d'>末页</a>" % (baseurl,totalpage) pager_list.append(last) result=''.join(pager_list) return mark_safe(result) #把字符串转成html语言
总结,分页时需要做三件事:
- 创建处理分页数据的类
- 根据分页数据获取数据
- 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]
Cookie
在浏览器端(客户端)保存的键值对,特性:每次http请求都会携带
1、获取Cookie
request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None) 参数: default: 默认值 salt: 加密盐 max_age: 后台控制过期时间
2、设置Cookie
def cook2(request): print(request.COOKIES) # print(request.get_signed_cookie('k2',None,salt='uuu')) # rep = HttpResponse('ok') # rep.set_cookie('k1',123) # rep.set_signed_cookie('k2',666,salt='uuu') rep = HttpResponse('ok') return rep
3、Cookie的参数
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.) 支持datetime、时间戳time.time这两种 path='/', Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问 domain=None, Cookie生效的域名 secure=False, https传输 httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
示例:
def cook1(request): # print(request.COOKIES) # 获取我所有Cookie # print(request.get_signed_cookie('k2',None,salt='uuu')) # 获取加盐的cookie # rep = HttpResponse('ok') # rep.set_cookie('k1',123) # 设置cookie # rep.set_signed_cookie('k2',666,salt='uuu') # 签名的cookie;salt为加盐 rep = HttpResponse('cook1') rep.set_cookie('k999', 123, path='/cook1/') # path是cookie生效的路径(局部的);/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问 rep.set_cookie('k888', 123) # 全局的cookie return rep
由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。
<script src='/static/js/jquery.cookie.js'></script> $.cookie("list_pager_num", 30,{ path: '/' });
Session
解析
生成随机字符串,并在服务端保存特定信息;
Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:
使用以下的类型只需要在引擎修改下配置换成相应的类型就可以了。
1、数据库(默认)
2、缓存
3、文件
4、缓存+数据库
5、加密cookie
1、数据库Session
Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
配置 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,默认修改之后才保存(默认)
使用 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")
示例:
def session(request): # request.session request.session['k1'] = 123 # 设置session # request.session['k1'] print(request.session.session_key) # 获得用户session的随机字符串(存在客户端浏览器中,也存在服务端的数据库中) return HttpResponse('session') def index(request): # 获得session return HttpResponse(request.session['k1']) # 这里可以直接读取到session
2、缓存Session
配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎 SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置 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,默认修改之后才保存
使用和数据库Session使用一样,只需要修改下配置就可以。
3、文件Session
配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎 SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() #如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T 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,默认修改之后才保存
使用同上,在settings中修改下配置
4、缓存+数据库Session
数据库用于做持久化,缓存用于提高效率 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
使用同上,在settings中修改下配置
5、加密cookie Session
配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
使用同上,在settings中修改下配置
登录认证实例:
<form class="common_form" id="Form" method="post" action="/app01/login/"> <div><h1 class="login_title">登录</h1></div> <div style="width: 600px"> <div class="form_group"><input name="username" class="form-control" label='用户名' type="text" placeholder="用户名" require='true'></div> </div> <div style="width: 600px"> <div class="form_group"><input name="password" class="form-control" label='密码' type="password" placeholder="密码" require='true'></div> </div> <div class="form_group"><input class="btn btn-info form_btn" type="submit" value="登录"></div> </form>
def login(request): if request.method == "POST": username = request.POST.get("username") password = request.POST.get("password") if username == "zhangsan" and password == "123456": request.session["IS_LOGIN"] = True #创建session return redirect("/app01/home/") return render(request,"app01/login.html") def home(request): islogin = request.session.get("IS_LOGIN",False) if islogin:#如果用户已登录 return render(request,"app01/menus.html") else: return redirect("/app01/login/") def logout(request):#退出 try: del request.session['IS_LOGIN'] except KeyError: pass return redirect("/app01/login/")
CSRF(跨站请求伪造)
1、简介
django为用户实现防止跨站请求伪造的功能,通过中间件django.middleware.csrf.CsrfViewMiddleware 来完成。
对于django中设置防跨站请求伪造功能分为全局和局部。
全局:
中间件 django.middleware.csrf.CsrfViewMiddleware
局部:
@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
@csrf_protect,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
默认(全局):'django.middleware.csrf.CsrfViewMiddleware' 中间间,过滤所有post的请求。是为全局的,需要遵循下面 在html中加上{% csrf_token %} views:的返回用render方法 去掉(全局):'django.middleware.csrf.CsrfViewMiddleware'就不需要遵循csrf 设置(局部)也可以通过装饰器来设定局部的CSRF。(指定某些遵循csrf) @csrf_protect 在html中加上{% csrf_token %} views:的返回用render 使用装饰器也可以(局部)不遵循CSRF(指定某些不遵循csrf) @csrf_exempt
2、应用
2.1、普通表单
veiw中设置返回值: return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))
# render_to_response需要context_instance=RequestContext(request)这个参数,因为render_to_response不生成随机字符串。
或者 return render(request, 'xxx.html', data) html中设置Token: {% csrf_token %}
2.2、Ajax
对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。
from django.template.context import RequestContext # Create your views here. def test(request): if request.method == 'POST': print request.POST return HttpResponse('ok') return render_to_response('app01/test.html',context_instance=RequestContext(request))
<!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) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ // 是一个全局的配置,在所有的ajax发来之前执行 beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); // 在发ajax之前设置一个请求头,名字是X-CSRFToken, // 在ajax发送之前把请求头放到csrftoken,在一块发过去,对的就执行 } } }); // 上面是获取token,在以后ajax操作前,写上面这个配置。 function Do(){ $.ajax({ url:"/app01/test/", data:{id:1}, type:'POST', success:function(data){ console.log(data); } }); } </script> </body> </html>
更多:https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
admin
django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,
就可以对数据进行增删改查,而使用django admin 则需要以下步骤:
1、创建后台管理员
2、配置url
3、注册和配置django admin后台管理页面
1、创建后台管理员
python manage.py createsuperuser
2、配置后台管理url
url(r'^admin/', include(admin.site.urls)),
3、注册和配置django admin 后台管理页面
a、在admin中执行如下配置
from django.contrib import admin from app01 import models admin.site.register(models.UserType) admin.site.register(models.UserInfo) admin.site.register(models.UserGroup) admin.site.register(models.Asset)
b、设置数据表名称
class UserType(models.Model): name = models.CharField(max_length=50) class Meta: verbose_name = '用户类型' verbose_name_plural = '用户类型'
c、打开表之后,设定默认显示,需要在model中作如下配置
class UserType(models.Model): name = models.CharField(max_length=50) def __unicode__(self): return self.name
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ('username', 'password', 'email') admin.site.register(models.UserType) admin.site.register(models.UserInfo,UserInfoAdmin) admin.site.register(models.UserGroup) admin.site.register(models.Asset)
d、为数据表添加搜索功能
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ('username', 'password', 'email') search_fields = ('username', 'email') admin.site.register(models.UserType) admin.site.register(models.UserInfo,UserInfoAdmin) admin.site.register(models.UserGroup) admin.site.register(models.Asset)
e、添加快速过滤
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ('username', 'password', 'email') search_fields = ('username', 'email') list_filter = ('username', 'email') admin.site.register(models.UserType) admin.site.register(models.UserInfo,UserInfoAdmin) admin.site.register(models.UserGroup) admin.site.register(models.Asset)
更多详见:http://www.cnblogs.com/wupeiqi/articles/5237704.html
http://www.cnblogs.com/wupeiqi/articles/5246483.html