杨梅冲
每天在想什么呢?

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")
ajax发送json格式数据

 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")
ajax发送文件

 

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">&laquo;</span>
      </a>
    </li>
        {{ page_html|safe }}
    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">&raquo;</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内置字段
View Code

字段校验

# 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版登陆验证思路

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相关设置
View Code

 

posted on 2019-09-05 15:05  杨梅冲  阅读(589)  评论(0编辑  收藏  举报