Web框架之Django_08 重要组件(form组件、cookie和session组件)

摘要:html

  • form组件前端

  • cookie组件git

  • session组件正则表达式

1、form组件

  • form介绍
    咱们以前在html页面中利用form表单向后端提交数据时候,都须要对用户的输入进行校验,好比校验用户是否输入正确(长度、格式...),若是用户输入的内容有误则须要在相应的位置显示对应的错误信息来提醒用户,提升前端的交互效率。
    Django form组件就是实现上述功能的一个功能组件。
    from组件主要功能有:
    # 生成页面可用的html标签
    # 对用户条件的数据进行校验
    # 保留上次输入内容
  • 先来看看本身手写注册功能的过程:
    # views.py # 注册
    def register(request): error_msg = ""
        if request.method == "POST": username = request.POST.get("name") pwd = request.POST.get("pwd") # 对注册信息作校验
            if len(username) < 6: # 用户长度小于6位
                error_msg = "用户名长度不能小于6位"
            else: # 将用户名和密码存到数据库
                return HttpResponse("注册成功") return render(request, "register.html", {"error_msg": error_msg}) # register.html
    !DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>注册页面</title>
    </head>
    <body>
    <form action="/reg/" method="post">
        <p> 用户名: <input type="text" name="name">
        </p>
        <p> 密码: <input type="password" name="pwd">
        </p>
        <p>
            <input type="submit" value="注册">
            <p style="color: red">{{ error_msg }}</p>
        </p>
    </form>
    </body>
    </html>
  • 校验数据
    使用form组件实现注册功能:数据库

    from django import forms # 按照Django form组件的要求本身写一个类
    class MyForm(forms.Form): name = forms.CharField(label='用户名', max_length=6) pwd = forms.CharField(label='密码', max_length=8, min_length=4) def register(request): form_obj = MyForm() if request.method == 'POST': # 实例化form对象的时候,把post提交过来的数据直接传进去
            form_obj = MyForm(request.POST) # 调用form_obj校验数据的方法
            if form_obj.is_valid():  # 这里is_valid()若是验证所有经过,则返回True
                return HttpResponse('注册成功') return render(request, 'register.html', {'form_obj': form_obj})

    这里咱们使用PythonConsole来测试:django

    依次输入:(带#的为结果)
    from app01 import views form_obj = views.MyForm({'name': 'hhh', 'pwd': '123'}) form_obj.is_valid() #False
    form_obj.errors #{'pwd': ['Ensure this value has at least 4 characters (it has 3).']}
    form_obj.cleaned_data #{'name': 'hhh'}

    ## form_obj.is_valid()  校验提交的信息,若是所有经过,则返回True,不然为False
    ## from_obj.errors 查看错误的信息,结果是一个字典格式,key为错误的字段,value为错误的缘由,注意这里面是一个列表,说明缘由能够有多个,这里须要说明:全部校验未经过的字段及错误信息提示都在这里放着,以键值对的形式存放。
    ## form_obj.cleaned_data  查看校验经过的数据,这里存放这全部校验经过的字段及其值,以字典形式存放。
    特别补充:
    若是:多串字段:不进行校验,因此不会在cleaned_data和errors中
               少传字段: 也会校验少传的字段,会在errors中,且该字段描述:{'pwd': ['This field is required.']}
    全部Form中的字段默认都是要校验,可是能够经过设置required = False来更过。后端

  • 渲染标签
    # views
    from django import forms # 按照Django form组件的要求本身写一个类
    class MyForm(forms.Form): name = forms.CharField(max_length=6) pwd = forms.CharField(max_length=8, min_length=4) def register(request): form_obj = MyForm() if request.method == 'POST': # 实例化form对象的时候,把post提交过来的数据直接传进去
            form_obj = MyForm(request.POST) # 调用form_obj校验数据的方法
            if form_obj.is_valid():  # 这里is_valid()若是验证所有经过,则返回True
                return HttpResponse('注册成功') return render(request, 'register.html', {'form_obj': form_obj})
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="/register/" method="post"> {# .as_p表明将全部的字段都对应input框渲染给前端显示#} {{ form_obj.as_p }} </form>
    </body>
    </html>

    能够看到,前面的Name和Pwd是Django本身渲染加上的,若是想要自定义,能够在MyForm类的对应字段里加上:label='用户名'和label='密码'便可浏览器

    上面是第一种渲染方式,能够看出可拓展性较差安全

  • 第二种渲染方式:
    多加几个校验字段
    from django import forms # 按照Django form组件的要求本身写一个类
    class MyForm(forms.Form): name = forms.CharField(max_length=6, label='用户名') pwd = forms.CharField(max_length=8, min_length=4, label='密码') email = forms.EmailField(label='邮箱')
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="/register/" method="post">
    <p>{{ form_obj.name }}</p>
    <p>{{ form_obj.pwd }}</p>
    <p>{{ form_obj.email }}</p>
    </form>
    </body>
    </html>

    只有input框!
    加入input框前的名字:服务器

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="/register/" method="post">
    <p>{{ form_obj.name.label }}{{ form_obj.name }}</p>
    <p>{{ form_obj.pwd.label }}{{ form_obj.pwd }}</p>
    <p>{{ form_obj.email.label }}{{ form_obj.email }}</p>
    </form>
    </body>
    </html>

    此种方法仍是有缺点,好比字段若是有100个,难道要100个所有输吗?因此应该还有更好的方法:

  • 第三种渲染方式:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="/register/" method="post"> {% for foo in form_obj %} <p>第三种渲染方式:{{ foo.label }}{{ foo }}</p> {% endfor %} </form>
    </body>
    </html>

    这里提一下:若是想要取消前端校验,能够在form表单中加入:novalidate
    这里须要知道:
        一、若是Django建立的form表单在提交的时候数据不合法(校验不经过),则会自动保留填写的信息,不会清空。
        二、Django建立的表单是没有提交按钮的,须要本身建立。
    接下来,添加校验不经过时候的提示信息:只需在恰当的位置添加

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="/register/" method="post" novalidate> {% for foo in form_obj %} <p>第三种渲染方式:{{ foo.label }}{{ foo }}<span>{{ foo.errors }}</span></p> {% endfor %} <input type="submit">
    </form>
    </body>
    </html>

    这里,提示错误信息在下面显示,若是想让它在每一个字段的input框后面显示能够加个0

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="/register/" method="post" novalidate> {% for foo in form_obj %} <p>第三种渲染方式:{{ foo.label }}{{ foo }}<span>{{ foo.errors.0 }}</span></p> {% endfor %} <input type="submit">
    </form>
    </body>
    </html>

    继续走向个性化:提示的错误信息是英文,我看不懂,那就改为中文:
    修改错误提示信息为自定义信息

    from django import forms # 按照Django form组件的要求本身写一个类
    class MyForm(forms.Form): name = forms.CharField(max_length=6, label='用户名', error_messages={ 'max_length': '用户名最大长度为6位', 'required': '用户名必须不能为空' }) pwd = forms.CharField(max_length=8, min_length=4, label='密码', error_messages={ 'max_length': '密码最大长度为8位', 'min_length': '密码最小长度为4位', 'required': '用户名必须不能为空' }) email = forms.EmailField(label='邮箱', error_messages={ 'required': '邮箱必须不能为空', 'invalid': '邮箱格式不合法' })

    测试测试:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="/register/" method="post" novalidate> {% for foo in form_obj %} <p>第三种渲染方式:{{ foo.label }}{{ foo }}<span>{{ foo.errors.0 }}</span></p> {% endfor %} <input type="submit">
    </form>
    </body>
    </html>

    这里有个小点须要说明:默认google浏览器的表单输入框若是要求最大6位,就只能输入6位最大,再多输入没有反应,这个为了测试方便,能够认为在每次提交前经过右键检查,人为删除限制的html代码

  • 经常使用字段与插件:
    这里系统的在补充一些Form类在建立的时候会涉及到的字段和插件,自对用于对用户请求数据的验证,插件用于自动生成html

    initial

    初始值,input框里面的初始值。

    class LoginForm(forms.Form):
        username = forms.CharField(
            min_length=8,
            label="用户名",
            initial="张三"  # 设置默认值
        )
        pwd = forms.CharField(min_length=6, label="密码")

    error_messages(这个上面以提到)

    重写错误信息。

    class LoginForm(forms.Form):
        username = forms.CharField(
            min_length=8,
            label="用户名",
            initial="张三",
            error_messages={
                "required": "不能为空",
                "invalid": "格式错误",
                "min_length": "用户名最短8位"
            }
        )
        pwd = forms.CharField(min_length=6, label="密码")

    PasswordInput
    给对应字段的input框设置属性,类....

    pwd = forms.CharField(max_length=8, min_length=4, label='密码', error_messages={ 'max_length': '密码最大长度为8位', 'min_length': '密码最小长度为4位', 'required': '用户名必须不能为空' }, widget=forms.widgets.PasswordInput(attrs={'type': 'password'})) # 将input改为password类型,这样输入的就不是明文了

    radioSelect

    将下拉式选择框转变成单选形式

    gender = forms.ChoiceField( choices=((1, ""), (2, ""), (3, "保密")), label="性别", initial=3, widget=forms.widgets.RadioSelect()

    单选Select

    class LoginForm(forms.Form):
        ...
        hobby = forms.ChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
            label="爱好",
            initial=3,
            widget=forms.widgets.Select()
        )

    多选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()
        )

    多选checkbox

    class LoginForm(forms.Form):
        ...
        hobby = forms.MultipleChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
            label="爱好",
            initial=[1, 3],
            widget=forms.widgets.CheckboxSelectMultiple()
        )

    choice字段注意事项

    在使用选择标签时,须要注意choices的选项能够配置从数据库中获取,可是因为是静态字段 获取的值没法实时更新,须要重写构造方法从而实现choice实时更新。

    方式一:

    from django.forms import Form
    from django.forms import widgets
    from django.forms import fields
    
     
    class MyForm(Form):
     
        user = fields.ChoiceField(
            # choices=((1, '上海'), (2, '北京'),),
            initial=2,
            widget=widgets.Select
        )
     
        def __init__(self, *args, **kwargs):
            super(MyForm,self).__init__(*args, **kwargs)
            # self.fields['user'].choices = ((1, '上海'), (2, '北京'),)
            # 或
            self.fields['user'].choices = models.Classes.objects.all().values_list('id','caption')

    方式二:

    from django import forms
    from django.forms import fields
    from django.forms import models as form_model
    
     
    class FInfo(forms.Form):
        authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())  # 多选
        # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())  # 单选
  • DjangoForm全部内置字段
    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内置字段
    全部内置字段
  • Hook方法(钩子函数)
    钩子函数分为:局部钩子和全局钩子
    这里还须要注意:钩子函数是在对校验经过的字段进行进一步校验。因此须要写在字段下面

    局部钩子

    咱们在Fom类中定义 clean_字段名() 方法,就可以实现对特定字段进行校验。

    # 局部钩子
        def clean_name(self): name = self.cleaned_data.get('name') if '666' in name: # 用add_error添加错误提示
                self.add_error('name', '666不对') return name

    全局钩子

    咱们在Fom类中定义 clean() 方法,就可以实现对字段进行全局校验。

    # 输入两次密码一致性的全局钩子
    设置两个密码字段 pwd = forms.CharField(max_length=8, min_length=4, label='密码', error_messages={ 'max_length': '密码最大长度为8位', 'min_length': '密码最小长度为4位', 'required': '用户名必须不能为空' }, widget=forms.widgets.PasswordInput(attrs={'type': 'password'})) confirm_pwd = forms.CharField(max_length=8, min_length=4, label='密码', error_messages={ 'max_length': '密码最大长度为8位', 'min_length': '密码最小长度为4位', 'required': '用户名必须不能为空' }, widget=forms.widgets.PasswordInput(attrs={'type': 'password'})) # 全局钩子:
        def clean(self): pwd = self.cleaned_data.get('pwd') confirm_pwd = self.cleaned_data.get('confirm_pwd') if pwd != confirm_pwd: self.add_error('confirm_pwd', '密码两次输入不一致') return self.cleaned_data

  • 最后说说注册的实际流程:也就是咱们经过校验成功后如何将注册信息存入数据库:
    def reg(request): # 生成一个空对象
        form_obj = MyForm() if request.method == 'POST': print(request.POST) form_obj = MyForm(request.POST) if form_obj.is_valid(): # print(form_obj.cleaned_data)
                # 这里打散传值须要注意的是模型表字段名要与模型中的字段名相同,否则确定会报错。
                # 因此平时要养成习惯,不少地方须要同样,以便于代码的可读性
                # models.User.objects.create(**form_obj.cleaned_data)
        return render(request,'reg.html',locals())

 2、cookie与session

  • Cookie介绍

    Cookie的由来

    你们都知道HTTP协议是无状态的。

    无状态的意思是每次请求都是独立的,它的执行状况和结果与前面的请求和以后的请求都无直接关系,它不会受前面的请求响应状况直接影响,也不会直接影响后面的请求响应状况。

    一句有意思的话来描述就是人生只如初见,对服务器来讲,每次的请求都是全新的。

    状态能够理解为客户端和服务器在某次会话中产生的数据,那无状态的就觉得这些数据不会被保留。会话中产生的数据又是咱们须要保存的,也就是说要“保持状态”。所以Cookie就是在这样一个场景下诞生。

    什么是Cookie

    Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。

    Cookie的原理

    cookie的工做原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能经过Cookie的内容来判断这个是“谁”了。

    查看Cookie

    咱们使用Chrome浏览器,打开开发者工具。

    还能够在这里查看:

    Django中操做Cookie

  • 前提:

  • 咱们在后端views中视图函数的返回参数render(),HttpResponse(),redirect(),经过查看它们的源码发现加括号后世界上返回的是一个对象,也就是咱们返回到前端的是一个对象,之前咱们是直接返回,如今要用到cookie和session就得在返回前对这个对象进行操做设置Cookie

    # views
    def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if username == 'sgt' and password == '123': # 用户登陆校验成功,下一步设置cookie,须要知道用哪个网页使用cookie
                obj = redirect('/index/') # 设置cookie
                obj.set_cookie('name', 'sgt', expires=15)  # 过时时间15秒
                return obj # 这个obj就是进行操做,设置好cookie的redirect('/index/')
        return render(request, 'login.html') def index(request): return render(request, 'index.html') # 在login.html登陆页面,进行登陆,若是用户名和密码为sgt和123,则跳转到inde.html,同时在跳转以前设置cookie,经过在index页面右键检查,查看cookie能够看到cookie也就存在,说明设置成功

    固然上面的设置cookie为了演示建立过程,并无加任何安全措施,在实际使用中咱们确定会对他进行加密处理:作一下更安全性的操做处理:

    obj.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

    request.COOKIES['key']
    request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

    参数:

    • default: 默认值
    • salt: 加密盐
    • max_age: 后台控制过时时间

    删除Cookie

    def logout(request):
        obj = redirect("/login/")
        obj.delete_cookie("user")  # 删除用户浏览器上以前设置的usercookie值
        return rep
    只有已经登陆了,才能访问网页,不然跳转到登陆页面,
    经过cookie来校验登陆,同时经过登陆装饰器来校验登陆,实现登陆后自动跳转到原来须要提示登陆的网页
    # 登陆页面视图函数
    def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if username == 'jason' and password == '123': old_path = request.GET.get('next') if old_path: # 若是原来页面有,则自动跳转
                    obj = redirect(old_path) else: # 若是是直接进入登陆页面,不是从其它页面跳转的,则默认跳到指定主页面去
                    obj = redirect('/home/') # 用户登陆成功 朝浏览器设置一个cookie
                obj.set_cookie('name','jason',expires=3600) # 这个兼容性更高
                # obj.set_cookie('name','jason',max_age=5)
                return obj return render(request,'login.html') # 登陆验证装饰器 
    from functools import wraps def login_auth(func): @wraps(func) def inner(request,*args,**kwargs): # 校验cookie
            # print(request.get_full_path())
            old_path = request.get_full_path()  # 拿到原来须要登陆的页面路由
            if request.COOKIES.get('name'): return func(request,*args,**kwargs) # 若是未登陆,跳转到登陆页面,同时在路由后面拼接老页面路由地址,用于登陆成功自动跳转
            return redirect('/login/?next=%s'%old_path) return inner @login_auth def index(request): # # print(request.COOKIES.get('name'))
        # if request.COOKIES.get('name'):
        return HttpResponse('我是index页面,只有登陆了才能看') @login_auth def home(request): return HttpResponse('我是home页面,只有登陆了才能看') @login_auth def xxx(request): return HttpResponse('我是xxx页面,只有登陆了才能看')
  • Session介绍

    Cookie虽然在必定程度上解决了“保持状态”的需求,可是因为Cookie自己最大支持4096字节,以及Cookie自己保存在客户端,可能被拦截或窃取,所以就须要有一种新的东西,它能支持更多的字节,而且他保存在服务器,有较高的安全性。这就是Session。

    问题来了,基于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的Cookie就起到桥接的做用。

    咱们能够给每一个客户端的Cookie分配一个惟一的id,这样用户在访问时,经过Cookie,服务器就知道来的人是“谁”。而后咱们再根据不一样的Cookie的id,在服务器上保存一段时间的私密资料,如“帐号密码”等等。

    总结而言:Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;可是Cookie以文本的形式保存在本地,自身安全性较差;因此咱们就经过Cookie识别不一样的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。

    另外,上述所说的Cookie和Session实际上是共通性的东西,不限于语言和框架。

  • session基本使用(设置,获取)
    # 设置session:

    request.session['name']='jason'

    设置session时候Django作了3件事:
    ①生成一个随机的字符串
    ②在Django的session表存储随机字符串与数据记录
    ③将随机字符串发送给浏览器
    # 获取session:

    request.session.get('name')
  • # Django中session的相关方法:

    # 获取、设置、删除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失效策略。

    # session解析
     

  • session版验证登陆

    # session版登陆
    def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if username == 'sgt' and password == '123456': # 设置session
                request.session['username'] = username # 跳转到登陆页面以前的URL
                next_url = request.GET.get('next') # 这里须要判断一下用户是不是跳转过来登陆的仍是直接登陆的
                if next_url:  # 若是有则跳转到原页面
                    return redirect(next_url) else:  # 不然默认指定跳转到指定页面
                    return redirect('/index/') return render(request, 'login.html') # 登陆验证装饰器: # 登陆验证的过程其实是基于已登陆的状态进行校验的,也就是说,用户登陆后, # 会在服务端生成一个cookie存储下来,同时把一份cookie再发给浏览器, # 当用户在某个跳转到某个须要登陆次才能访问的页面时候,就会进行登陆校验过程 # 会将浏览器的cookie发到服务端,和服务端存储的cookie进行匹配,若是匹配到,就说明 # 服务端已经记录这这个用户的登陆状态,容许访问。
    
    
    from functools import wraps def login_auth(func): def inner(request, *args, **kwargs): # 获取到验证登陆的当前页面的所有路由
            next_url = request.get_full_path() # 若是改用户的session存在,说明已登陆
            if request.session.get('username'): return func(request, *args, **kwargs) # 发现未登陆,则跳转到登陆页面,同时路由后面拼接当前页面路由
            else: return redirect('/login/?next=%s' % next_url) return inner @login_auth def logout(request): # 删除全部当前请求相关的session
     request.session.delete() return redirect("/login/") @login_auth def index(request): current_user = request.session.get("user", None) return render(request, "index.html", {"user": current_user})
  • FBV加装饰器(前面cookie和session加装饰器都是使用FBV)
  • CBV加装饰器:
    # 须要导入一个method_decorator模块
    from django.utils.decorators import method_decorator 其它都同样,主要在装饰的方法上有区别: # @method_decorator(login_auth,name='get') # 第二种 name参数必须指定
        class MyHome(View): @method_decorator(login_auth) # 第三种 get和post都会被装饰
            def dispatch(self, request, *args, **kwargs): super().dispatch(request,*args,**kwargs) # @method_decorator(login_auth) # 第一种
            def get(self,request): return HttpResponse('get') def post(self,request): return HttpResponse('post')
相关文章
相关标签/搜索