1.MTV与MVC
框架类型:
MVC:
M:models
V:views
C:controller
Django用的框架就是MTV
MTV:
M:models
T:templates
V:views
ps:MTV本质也是MVC,叫法不同
一、AJAX简介
# 名称:异步的Javascript和XML # 特点: 局部刷新、异步提交:AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容
# ajax 发送普通数据 # 前端必须导入jquery # 实例:写出一个加法运算页面 # urls.py url(r'^index/', views.index), # views.py def index(request): if request.method == 'POST': print(request.POST) # 后端获取到的前端提交的数据,默认都是字符串类型 i1 = request.POST.get('i1') i2 = request.POST.get('i2') # 可以做一个数字判断 res = int(i1) + int(i2) return HttpResponse(res) return render(request,'index.html') # 前端<head>里需要导入jquery <body> <input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"> <button id="b1">计算</button> <script> $('#b1').click(function () { $.ajax({ url:'', //控制数据提交目的地,不写默认就是当前页面所在的url type:'post', // 控制提交方式 data:{'i1':$('#i1').val(),'i2':$('#i2').val()}, //提交的数据 success:function (data) { // 形参data接收到的就是异步提交返回的结果 $('#i3').val(data) } }) }) </script> </body>
1.1 ajax基本语法结构
$.ajax({ url:'', //控制数据提交目的地,不写默认就是当前页面所在的url type:'post', // 控制提交方式 data:{'i1':$('#i1').val(),'i2':$('#i2').val()}, //提交的数据 success:function (data) { // data接收到的就是异步提交返回的结果,这里的data和上面的data无关 $('#i3').val(data) } })
1.2 ajax前后端传输数据编码格式
1.发送普通数据(前例)
2.发送json格式数据
django针对json格式的数据 不做任何处理
3.ajax发送文件
需要借助于内置对象FormData
# 浏览器上ContentType:表示数据的编码格式,告诉后端这个数据的格式 # 编码格式: 1.utlencoded:是form表单和ajax都默认的编码格式 urlencoded数据格式: i1=1&i2=2 #加法页面 # django后端会将符合urlencode编码格式的数据 解析并放入request.POST中
2.application/json
3.formdata
# 基本使用 数据格式和编码要一致,不能数据时urlencoded格式 编码却指定成了json格式 # 前端json格式转换 JSON.stringify({'name':'simon','password':'123'}) # 等价于 json.dumps() JSON.parse() # 等价于json.loads()
# 前端,绑定事件 <button id="b1">计算</button> <script> $('#b1').click(function () { $.ajax({ url: '/json/', type: 'post', data: JSON.stringify({'name': 'simon', 'password': '123'}), //前端转json格式 contentType: 'application/json', // 如果不指定编码,后端会出现数据错乱的现象 success: function (data) { alert(data) } }) }) </script> # views.py import json def jason(request): if request.method == 'POST': print(request.POST) # <QueryDict: {}> 针对json格式数据,不做处理,不会放到request.post中,放到request.body中 print(request.body) # 原始数据 b'{"name":"simon","password":"123"}' res = json.loads(request.body.decode('utf-8')) print(res,type(res)) # {'name': 'simon', 'password': '123'} <class 'dict'> return HttpResponse("OK")
formdata:文件交互,获取用户上传的文件
# 前端 <input type="file" id="myfile"> </script> //ajax发送文件 $('#b1').click(function () { // ajax发送文件一定要借助内置对象:先生成一个内置对象 //formData不仅可以传文件,也可以传普通的键值对,符合urlencoded编码格式的数据 var formData = new FormData(); //以添加键值对的方式,往formdata中添加数据 // 获取文件input框中对应的文件对象,固定语法 $('#myfile')[0].files[0] formData.append('myfile',$('#myfile')[0].files[0]); formData.append('username','simon'); $.ajax({ url:'/json/', type:'post', data: formData, // ajax发送文件需要记住的参数 processData: false, //不要处理formdata格式数据 contentType: false, //不需要指定任何编码,formdata自带编码 success:function (data) { alert(data) } }) }) </script> # 后端views.py def jason(request): if request.method == 'POST': print(request.POST) # 传普通键值对<QueryDict: {'username': ['simon']}> print(request.FILES) # 获取前端传输的文件 <MultiValueDict: {'myfile': [<InMemoryUploadedFile: 周末四期前端jq+bs.md (application/octet-stream)>]}> # 获取文件对象:可以当成文件句柄:with open(...) as f的那个f file_obj = request.FILES.get('myfile') print(file_obj.name) # 查看文件名 with open(file_obj.name,'wb') as f: for line in file_obj: f.write(line) return HttpResponse("OK")
1.3 AJAX常见的应用场景
搜索引擎根据用户输入的关键字,自动提示检索关键字
还有一个很重要的应用场景就是注册时候的用户名的查重
这里就使用了AJAX技术!当文件框发生了输入变化时,使用AJAX技术向服务器发送一个请求,然后服务器会把查询到的结果响应给浏览器,最后再把后端返回的结果展示出来
整个过程中页面没有刷新,只是刷新页面中的局部位置而已
当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!
只要input框内有变化,就返回提示:
二、批量插入及自定义分页使用
2.1数据的批量插入
# views.py from app01 import models def login(request): # 插入数据很慢 # for i in range(1000): # models.Book.objects.create(name='第%s本书'%i) # 一次一次性插入数据 # 批量插入方式 b_list = [] for i in range(10000): b_list.append(models.Book(name='第%s本书'%i)) models.Book.objects.bulk_create(b_list) # 统一一次性插入数据 return render(request,'list.html',locals()) # 前端页面展示 {% for foo in queryset %} <p>{{ foo.name }}</p> {% endfor %}
2.2 自定义分页
# 分页器的推演 def login(request): # 当前页(总共10000条数据) current_page = request.GET.get('page',1) current_page = int(current_page) # 每页展示的条数 per_page_num = 10 queryset = models.Book.objects.all() all_count = queryset.count() # 数据的总条数 queryset = models.Book.objects.all()[(current_page - 1) * per_page_num:current_page * per_page_num] # page_num总页数,more大于0页数就加1 page_num,more = divmod(all_count,per_page_num) if more: page_num += 1 page_html = '' for i in range(1,page_num): res = '<li><a href="?page=%s">%s</a></li>'%(i,i) page_html += res return render(request,'list.html',locals()) # 前端 <body> {% for foo in queryset %} <p>{{ foo.name }}</p> {% endfor %} <nav aria-label="Page navigation"> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> {{ page_html|safe }} <li> <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </nav> </body> # 上面代码出现会将所有分页都列出来,所以最终版本分页代码 https://www.cnblogs.com/yangmeichong/p/11460004.html
引用代码后:
#分页代码可以放到别的目录mypage.py
# 分页器的使用:只需要获取需要展示的数据,然后获取总条数,获取当前页 # 后端代码views.py def login(request): from app01.urils import mypage queryset = models.Book.objects.all() current_page = request.GET.get('page',1) all_count = queryset.count() page_obj = mypage.Pagination(current_page=current_page,all_count=all_count) page_queryset = queryset[page_obj.start:page_obj.end] # 之后将页面中 return render(request,'list.html',locals()) # 前端代码 <body> {% for foo in page_queryset %} <p>{{ foo.name }}</p> {% endfor %} {{ page_obj.page_html|safe }} </body> # 每页展示的条数和显示几个分页都可以在mypage.py中修改
三、forms组件校验数据
forms组件能够干的事 1.前端页面搭建 2.后端数据校验 3.展示错误信息
通常用来写注册页面
1.获取用户输入
2.判断用户输入是否合法
3.如果不合法展示错误信息
3.1 后端数据校验
forms组件中字段默认都是必须传值的
forms组件默认不能少传字段,但是可以多传字段,多传的字段form组件直接忽略不考虑
后端代码pycharm测试方式:Python Console
# views.py class MyRegForm(forms.Form): name = forms.CharField(max_length=8) # name字段最大只能是八位 password = forms.CharField(max_length=8,min_length=3) # 最大八位 最少三位 email = forms.EmailField() # email字段接收的数据 必须符合邮箱格式 #forms组件的使用 第一步生成一个继承form类的类;forms组件不能少传值 >>>from app01 import views >>>obj = views.MyRegForm({"name":'simon','password':'12','email':'123'}) # 判断信息是否完全合法 >>>obj.is_valid() # 获取字段及错误信息 >>>obj.errors {'password': ['Ensure this value has at least 3 characters (it has 2).'], 'email': ['Enter a valid email address.']} # 获取符合条件的数据 >>>obj.cleaned_data {'name': 'simon'}
3.2 渲染标签
# 后端:新增reg与MyRegForm连用 def reg(request): form_obj = MyRegForm() return render(request,'myform.html',locals()) #前端 <p>第一种方式:本地测试使用</p> {#as_p: 生成标签以p标签包裹的形式#} {{ form_obj.as_p }} {#as_ul:生成以ul包裹的li标签#} {{ form_obj.as_ul }} {#as_table:以表格的形式展开#} {{ form_obj.as_table }} <p>第二种方式</p> {{ form_obj.name.label }}{{ form_obj.name }} {{ form_obj.password.label }}{{ form_obj.password }} <form action="" method="post"> <p>第三种方式:推荐使用</p> {% for foo in form_obj %} {{ foo.label }}{{ foo }} {% endfor %} <input type="submit"> </form>
3.3 forms组件展示信息
# views.py from django import forms from django.forms import widgets class MyRegForm(forms.Form): name = forms.CharField(max_length=8,label="用户名",error_messages={ "max_length":"用户名最长8位", "required":"用户名不能为空", },widget=widgets.TextInput(attrs={'class':'c1'})) password =forms.CharField(max_length=8,min_length=3,label="密码",error_messages={ "max_length":"密码最长8位", "min_length":"密码最短3位", "required":"密码不能为空", },widget = widgets.PasswordInput(attrs={'class':'form-control'})) email = forms.EmailField(error_messages={ "invalid": "邮箱格式错误", })
gender = forms.fields.ChoiceField(
choices=((1, "男"), (2, "女"), (3, "保密")),
label="性别",
initial=3,
widget=forms.widgets.RadioSelect()
)
def reg(request): form_obj = MyRegForm() if request.method == 'POST': form_obj = MyRegForm(request.POST) if form_obj.is_valid(): return HttpResponse('OK') return render(request,'myform.html',locals()) # 前端 <form action="" method="post" novalidate> {#novalidate: 取消前端校验#} <p>第三种方式:推荐使用</p> {% for foo in form_obj %} <p> {{ foo.label }}:{{ foo }} {{ foo.errors.0 }} {% endfor %} </p> <input type="submit"> </form>
3.4 钩子函数
from django import forms from django.forms import widgets class MyRegForm(forms.Form): name = forms.CharField(max_length=8,label="用户名",error_messages={ "max_length":"用户名最长8位", "required":"用户名不能为空", },widget=widgets.TextInput(attrs={'class':'c1'})) password =forms.CharField(max_length=8,min_length=3,label="密码",error_messages={ "max_length":"密码最长8位", "min_length":"密码最短3位", "required":"密码不能为空", },widget = widgets.PasswordInput(attrs={'class':'form-control'})) confirm_password =forms.CharField(max_length=8,min_length=3,label="密码",error_messages={ "max_length":"密码最长8位", "min_length":"密码最短3位", "required":"密码不能为空", },widget = widgets.PasswordInput(attrs={'class':'form-control'})) email = forms.EmailField(error_messages={ "invalid": "邮箱格式错误", })
gender = forms.fields.ChoiceField(
choices=((1, "男"), (2, "女"), (3, "保密")),
label="性别",
initial=3,
widget=forms.widgets.RadioSelect()
)
# 钩子函数:全局钩子与局部钩子 # 局部钩子:校验单个字段 def clean_name(self): name = self.cleaned_data.get('name') if '666' in name: self.add_error('name',"光喊666是不行的") return name # 全局钩子:同时校验多个字段;例如密码和确认密码 def clean(self): password = self.cleaned_data.get("password") confirm_password = self.cleaned_data.get('confirm_password') if not password == confirm_password: self.add_error('confirm_password','2次密码不一致') return self.cleaned_data
forms组件更详细方法:https://www.cnblogs.com/Dominic-Ji/p/9240365.html
# 多选select class LoginForm(forms.Form): ... hobby = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ), label="爱好", initial=[1, 3], widget=forms.widgets.SelectMultiple() ) # 单选checkbox class LoginForm(forms.Form): ... keep = forms.ChoiceField( label="是否记住密码", initial="checked", widget=forms.widgets.CheckboxInput() )
Django Form所有内置字段
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) 格式: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类型 Django Form内置字段
字段校验
# RegexValidator验证器 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'邮箱'}))
四、cookie session
cookie原理:
cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie的内容来判断这个是“谁”了
cookie:就是保存在浏览器上的键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。
Django中操作cookie
# views.py def index1(request): obj = HttpResponse('ok') obj.set_cookie('name','simon') # 设置cookie return obj # 访问后可以看到浏览器的cookie 中有一个键值对:name:simon def home(request): if request.COOKIES.get('name'): # 获取cookie return HttpResponse("登录成功") else: return HttpResponse("去登录") # 访问home页面可以看到上面的键值对,但是清空后就会返回去登录的提示
获取cookie参数:
default 默认值
salt 加密盐
max_age 后台控制过期时间
获取cookie:
request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
设置cookie:
rep = HttpResponse(...) rep = render(request, ...) rep.set_cookie(key,value,...) rep.set_signed_cookie(key,value,salt='加密盐', max_age=None, ...)
参数
参数: 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
def logout(request): rep = redirect("/login/") rep.delete_cookie("user") # 删除用户浏览器上之前设置的usercookie值 return rep
session由来:
Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是Session
session:就是保存在服务器的上的键值对(信息),下次访问
Django中Session相关方法
注意:django用session一定要先初始化django默认的那些表
django服务端会自动生成一串随机字符串 保存到浏览器上 键固定就叫sessionid;数据库的session表中会多出一条记录,名字和浏览器中sessionid对应的value值一样的session_key;session_key对应的session_data是加密的,后面就是sessionid过期时间
django默认的session过期时间是14天
# 设置session def index1(request): request.session['name'] = 'simon' # 设置session return HttpResponse('index1') # 获取session def home(request): if request.session.get('name'): return HttpResponse("登录成功") else: return HttpResponse("去登录")
# 获取、设置、删除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的key request.session.session_key # 将所有Session失效日期小于当前日期的数据删除 request.session.clear_expired() # 检查会话session的key在数据库中是否存在 request.session.exists("session_key") # 删除当前会话的所有Session数据 request.session.delete() # 删除当前的会话数据并删除会话的Cookie。 request.session.flush() 这用于确保前面的会话数据不可以再次被用户的浏览器访问 例如,django.contrib.auth.logout() 函数中就会调用它。 # 设置会话Session和Cookie的超时时间 request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。
作业:
index home xxx
基于session写一个登录验证
比如说有是个视图函数 必须用户登录之后才能查看
你写一个装饰器完成该功能
拔高:用户登录完成后跳转到用户没有登录之前想要访问的那个页面
from functools import wraps def check_login(func): @wraps(func) def inner(request, *args, **kwargs): next_url = request.get_full_path() if request.session.get("user"): return func(request, *args, **kwargs) else: return redirect("/login/?next={}".format(next_url)) return inner def login(request): if request.method == "POST": user = request.POST.get("user") pwd = request.POST.get("pwd") if user == "alex" and pwd == "alex1234": # 设置session request.session["user"] = user # 获取跳到登陆页面之前的URL next_url = request.GET.get("next") # 如果有,就跳转回登陆之前的URL if next_url: return redirect(next_url) # 否则默认跳转到index页面 else: return redirect("/index/") return render(request, "login.html") @check_login def logout(request): # 删除所有当前请求相关的session request.session.delete() return redirect("/login/") @check_login def index(request): current_user = request.session.get("user", None) return render(request, "index.html", {"user": current_user}) Session版登录验证
session流程
request.session['k1'] = 'xxx' """ 1.内部自动生成一个随机字符串 2.将键值对保存到django_session表中 3.将生成的随机字符串发送给浏览器保存起来 """ request.session.get('k1') """ 1.内部自动获取浏览器的随机字符串 2.取django_session表中依次查找 3.获取对应的信息 赋值给request.session """
Django中的session设置
Django中默认支持Session,其内部提供了5种类型的Session供开发者使用。
1. 数据库Session SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认) 2. 缓存Session SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎 SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置 3. 文件Session SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎 SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() 4. 缓存+数据库 SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎 5. 加密Cookie Session SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎 其他公用设置项: 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,默认修改之后才保存(默认) Django中Session相关设置