zoukankan      html  css  js  c++  java
  • django之forms组件和cookie与session操作

    django之forms组件和cookie与session操作

    forms组件

    forms主要功能

    生成页面可用的HTML标签
    对用户提交的数据进行校验
    保留上次输入内容
    

    注意点:

    注册页面:
    用户点击注册发送到后端做用户名密码的校验。
    用户不能含敏感词,不符合社会主义核心价值观。
    密码不能为空。
    

    需求:

    我们写一个注册页面 获取用户输入的用户名和密码
    用户点击注册发送到后端做用户名密码的校验
    用户名中不能包含金坪梅 			不符合社会主义核心价值观
    密码不能为空					你个DSB,密码怎么能为空
    
    1.手写获取用户输入的前端页面代码					渲染页面
    2.后端获取用户数据并做合法性校验					校验数据
    3.将校验之后的结果渲染到前端页面					展示信息
    

    普通方式手写注册功能

    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})
    

    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>注册页面</title>
    </head>
    <body>
    <form action="/reg/" method="post">
        {% csrf_token %}
        <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>
    

    forms组件

    		1.渲染页面
    		2.校验数据
    		3.展示信息
    

    先定义一个类和导入:

    from django import forms
    # max_length  准许输入最常位。。。
    # min_length  最少为。。。。
    
    from django import forms
    
    
    class MyRegForm(forms.Form):
        # 用户名最少3位最多8位
        username = forms.CharField(max_length=8,min_length=3)
        password = forms.CharField(max_length=8,min_length=3)
        # email字段必须填写符合邮箱格式的数据
        email = forms.EmailField()
    		
    

    如何校验数据

    1.传入待校验的数据  用自己写的类 传入字典格式的待校验的数据
    2.判断数据是否符合校验规则    is_valid()
      # 该方法只有在所有的数据全部符合校验规则才会返回True
    3.如何获取校验之后通过的数据   cleaned_data
    4.如何获取校验失败及失败的原因  errors
    5.注意 forms组件默认所有的字段都必须传值 也就意味着传少了是肯定不行的 而传多了则没有任何关系 只校验类里面写的字段 多传的直接忽略了
    
    
    # 1.传入待校验的数据  用自己写的类 传入字典格式的待校验的数据
    form_obj = views.MyRegForm({'username':'jason','password':'12','email':'123456'})
    # 2.判断数据是否符合校验规则
    form_obj.is_valid()  # 该方法只有在所有的数据全部符合校验规则才会返回True
    False
    # 3.如何获取校验之后通过的数据
    form_obj.cleaned_data
    {'username': 'jason'}
    # 4.如何获取校验失败及失败的原因
    form_obj.errors
    {
        'password': ['Ensure this value has at least 3 characters (it has 2).'],
        'email': ['Enter a valid email address.']
    }
    # 5.注意 forms组件默认所有的字段都必须传值 也就意味着传少了是肯定不行的 而传多了则没有任何关系 只校验类里面写的字段 多传的直接忽略了
    form_obj = views.MyRegForm({'username':'jason','password':'123456'})
    form_obj.is_valid()
    Out[12]: False
    form_obj.errors
    Out[18]: {'email': ['This field is required.']}
        
        
    form_obj = views.MyRegForm({'username':'jason','password':'123456',"email":'123@qq.com',"hobby":'hahahaha'})
    form_obj.is_valid()
    Out[14]: True
    form_obj.cleaned_data
    Out[15]: {'username': 'jason', 'password': '123456', 'email': '123@qq.com'}
    form_obj.errors
    Out[16]: {}
    
    

    如何渲染页面的三种方法

    先定义一个类:
    forms组件只帮你渲染获取用户输入(输入 选择 下拉 文件)的标签 不渲染按钮和form表单标签,渲染出来的每一个input提示信息都是类中字段首字母大写。
    
    

    第一种方法:

    优点:

    多个p标签,本地测试方便。
    
    

    缺点:

    封装程度太高了 不便于扩展
    
    
    <p>第一种渲染方式:多个p标签  本地测试方便 封装程度太高了 不便于扩展</p>
        {{ form_obj.as_p }}
        {{ form_obj.as_ul }}
        {{ form_obj.as_table }}
    
    

    效果:


    第二种方法:

    优点:

    扩展性较高 书写较为繁琐
    
    
    <p>第二种渲染方式:  扩展性较高 书写较为繁琐</p>
    <label for="{{ form_obj.username.id_for_label }}">{{ form_obj.username.label }}</label>
    {{ form_obj.username }}
    {{ form_obj.password.label }}{{ form_obj.password }}
    {{ form_obj.email.label }}{{ form_obj.email }}
    
    

    效果:

    第三种方法:推荐使用

    优点:

    使用效率高,减少代码冗余
    
    
    <p>第三种渲染方式  推荐使用</p>
    {% for form in form_obj %}
    <p> {{ form.label }}{{ form }}</p>
    #可提前设置一个错误判断的语句
    <span>{{from.errors.}}</span>
    {% endfor %}
    
    

    效果:

    如何渲染错误信息

    导入:

    from django.shortcuts import render,HttpResponse,redirect
    
    

    前端:

    <form action="" method="post" novalidate>
    	{% for form in form_obj %}
    	<p>
    		{{ form.label }}{{ form }}
    		<span>{{ form.errors.0 }}</span>  # 这个是模板语法 索引不会出现超出报错
    	</p>
    	{% endfor %}
    	<input type="submit">
    </form>
    
    

    后端:

    def reg(request):
        # 1 先生成一个空的类对象
        form_obj = MyRegForm()
        if request.method == 'POST':
            # 3 获取用户数据并交给forms组件校验  request.POST
            form_obj = MyRegForm(request.POST)
            # 4 获取校验结果
            if form_obj.is_valid():
                return HttpResponse('数据没问题')
            else:
                # 5 获取校验失败的字段和提示信息
                print(form_obj.errors)
    
                # 2 直接将该对象传给前端页面
        return render(request,'reg.html',locals())
    
    

    固定错误信息是一个列表,索引取0的位置

    label 将英文修改成中文

    效果:(用户名:最长8位 不然报错)

    校验:邮箱格式是否正确

    效果:

    forms的常用参数

    label    			input的提示信息
    error_messages   	自定义报错的提示信息
    required     		设置字段是否允许为空
    initial             设置默认值
    widget              控制type类型及属性
    
    widget=forms.widgets.TextInput(attrs={'class':'form-control c1 c2'})
                                   widget=forms.widgets.PasswordInput(attrs={'class':'form-control'})
                                   
    validator 正则校验及报错信息并支持多个。
    
    

    导入:

    from django.forms import widgets
    
    
    widget=forms.widgets.TextInput(attrs={'class':'form-control c1  c2'})
                                   widget=forms.widgets.PasswordInput(attrs={'class':'form-control'})
    
    

    钩子函数:

    # 如果你想同时操作多个字段的数据你就用全局钩子
    # 如果你想操作单个字段的数据 你就用局部钩子
    
    

    全局钩子

    针对多个字段

    校验两次密码是否一直

    # 全局钩子
    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','两次密码不一致')
        return self.cleaned_data
    
    

    效果:

    局部钩子

    针对单个字段

    # 局部钩子
    校验用户名是否存在
    from app01 import models
    
    def clean_username(self):
        username = self.cleaned_data.get('username')
        if '666' in username:
            self.add_error('username','光喊666是不行的')
        return username
    
        # 如果你想同时操作多个字段的数据你就用全局钩子
        # 如果你想操作单个字段的数据 你就用局部钩子
    
    

    校验用户名中不能包含666

    正则简单用法:

    导入:

    from django.core.validators import RegexValidator
    
    
    正则校验
    phone = forms.CharField(
        validators=[
            RegexValidator(r'^[0-9]+$', '请输入数字'),
            RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
        ]
    )
    
    

    基于使用form组件实现注册功能

    views.py

    先定义好一个RegForm类:

    导入:from django import forms
    
    # 按照Django form组件的要求自己写一个类
    class RegForm(forms.Form):
        name = forms.CharField(label="用户名")
        pwd = forms.CharField(label="密码")
    
    

    写一个视图函数

    # 使用form组件实现注册方式
    def register2(request):
        form_obj = RegForm()
        if request.method == "POST":
            # 实例化form对象的时候,把post提交过来的数据直接传进去
            form_obj = RegForm(request.POST)
            # 调用form_obj校验数据的方法
            if form_obj.is_valid():
                return HttpResponse("注册成功")
        return render(request, "register2.html", {"form_obj": form_obj})
    
    

    login2.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>注册2</title>
    </head>
    <body>
        <form action="/reg2/" method="post" novalidate autocomplete="off">
            {% csrf_token %}
            <div>
                <label for="{{ form_obj.name.id_for_label }}">{{ form_obj.name.label }}</label>
                {{ form_obj.name }} {{ form_obj.name.errors.0 }}
            </div>
            <div>
                <label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
                {{ form_obj.pwd }} {{ form_obj.pwd.errors.0 }}
            </div>
            <div>
                <input type="submit" class="btn btn-success" value="注册">
            </div>
        </form>
    </body>
    </html>
    
    

    forms实现的网页效果的功能:

    • 前端页面是form类的对象生成的                                      -->生成HTML标签功能
    • 当用户名和密码输入为空或输错之后 页面都会提示        -->用户提交校验功能
    • 当用户输错之后 再次输入 上次的内容还保留在input框   -->保留上次输入内容
    
    

    cookie与session操作

    Cookie的介绍

    当你第一次登陆成功之后 服务端给你返回了一个随机字符串
    保存客户端浏览器上 之后再次朝服务端发请求 只需要携带该随机字符串
    服务端就能够识别当前用户身份
    超时时间的概念
    
    cookie虽然是保存在客户端的浏览器上的 但是是服务端设置的
    浏览器也是可以拒绝服务端对要求 不保存cookie
    
    

    什么是Cookie

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

    Cookie的原理

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

    查看****Cookie

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

    Django中操作Cookie

    一定要利用HttpResponse 类直接或间接产生的对象
    
    

    设置:

    obj = HttpResponse('.......')
    obj.set_cookie(k,v)
    可以设置超时时间
    
    
    
    

    获取

    request.COOKIES.get['key']
    
    

    删除

    obj = HttpResponse('.......')
    obj.delete_cookie(k,v)
    
    

    获取Cookie

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

    保存在客户端浏览器上的键值对

    	cookie
    		保存在客户端浏览器上的键值对
    		return HttpResponse('...')
    		
    		return render(...)
    		
    		return redirect(...)
    		
    		# 变形
    		obj = HttpResponse('...')
    		return obj
    		
    		obj1 = render(...)
    		return obj1
    		
    		obj2 = redirect(...)
    
    		设置cookie
    			obj.set_cookie()
    		获取cookie
    			request.COOKIES.get()
    		删除cookie
    			obj.delete_cookie()
    
    
    # 装饰器模板
    from functools import wraps
    
    
    def login_auth(func):
        @wraps(func)
        def inner(request,*args,**kwargs):
            # print('request.path_info:',request.path_info)
            # print('request.get_full_path():',request.get_full_path())
            # 执行被装饰函数之前你可以做的事情
            target_url = request.path_info
            if request.COOKIES.get('username'):
                res = func(request,*args,**kwargs)
                return res
            else:
                return redirect('/login/?next=%s'%target_url)
        return inner
    
    
    print('request.path_info:',request.path_info)  # 只拿路径部分 不拿参数
    print('request.get_full_path():',request.get_full_path())  # 路径加参数
    request.path_info: /home/
    
        request.get_full_path(): /home/?username=jason&password=123
    
    

    Session

    Cookie  支持字节相对session少,本身保存在客户端,可能被拦截或窃取
    能支持更多的字节,保存在服务器,有较高的安全性
    
    

    总结:

    Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。
    
    

    保存在服务端上的键值对

    设置:

    request.session['key'] = value
    
    request.session['username'] = 'jason'
    
    
    
    1.django内部会自动生成一个随机字符串
    2.去django_session表中存储数据 键就是随机字符串 值是要保存的数据(中间件干的)
    3.将生成好的随机字符串返回给客户端浏览器   浏览器保存键值对
    sessionid  随机字符串
    
    

    获取

    request.session.get('key')
    
    request.session.get('username')
    
    
    1.django会自动取浏览器的cookie查找sessionid键值对 自动取请求头中查找cookie锁携带的键值对,获取随机字符串
    2.拿着该随机字符串取django_session表中比对数据
    3.如果比对上了 就将随机字符串对应的数据获取出来并封装到request.session供用户调用
    
    

    django中默认的session超时时间为14天

    删除当前会话的所有Session数

    request.session.flush() #推存
    
    request.session.delete()
    
    
    这用于确保前面的会话数据不可以再次被用户的浏览器访问
    例如,django.contrib.auth.logout() 函数中就会调用它。
    
    session是保存在服务端
    
    

    设置会话Session和Cookie的超时时间

    request.session.set_expiry(value)
    
    
    * 如果value是个整数,session会在些秒数后失效。
    * 如果value是个datatime或timedelta,session就会在这个时间后失效。
    * 如果value是0,用户关闭浏览器session就会失效。
    * 如果value是None,session会依赖全局session失效策略。
    
    
    

    验证以上cookie和session的代码

    装饰器模板 views.py

    from functools import wraps
    
    
    def login_auth(func):
        @wraps(func)
        def inner(request,*args,**kwargs):
            # print('request.path_info:',request.path_info)
            # print('request.get_full_path():',request.get_full_path())
            # 执行被装饰函数之前你可以做的事情
            target_url = request.path_info
            if request.COOKIES.get('username'):
                res = func(request,*args,**kwargs)
                return res
            else:
                return redirect('/login/?next=%s'%target_url)
        return inner
    
    

    登录功能 views.py

    def login(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            if username == 'jason' and password == '123':
                # target_url = request.GET.get("next",'/home/')
                target_url = request.GET.get("next")
                # 判断用户登录之前是否有想要访问的url
                if target_url:
                    # 保存用户登录状态
                    obj = redirect(target_url)
                else:
                    obj = redirect('/home/')
                # 设置cookie
                obj.set_cookie('username','jason666',max_age=3)
                return obj
        return render(request,'login.html')
    
    

    校验浏览器是否有对应的cookie

    @login_auth
    def home(request):
        # 校验浏览器是否有对应的cookie
        # if request.COOKIES.get('username'):
        #     print(request.COOKIES)
        #     return HttpResponse("我是home页面 只有登录的用户才能访问")
        # else:
        #     return redirect('/login/')
        return HttpResponse("我是home页面 只有登录的用户才能访问")
    
    
    @login_auth
    def index(request):
        return HttpResponse('我是index页面 只有登录之后的用户才能看')
    
    
    @login_auth
    def demo(request):
        return HttpResponse('我是demo页面 只有登录之后的用户才能看')
    
    
    @login_auth
    def logout(request):
        obj = HttpResponse('注销了')
        obj.delete_cookie('username')
        return obj
    
    
    def set_session(request):
        # request.session['username'] = 'egondsb'
        request.session['name'] = 'egon'
        # request.session.set_expiry(5)
        return HttpResponse("set_session")
    
    
    def get_session(request):
        # print(request.session)  # <django.contrib.sessions.backends.db.SessionStore object at 0x00000259F72683C8>
    
        print(request.session.get('name'))
    
        return HttpResponse("get_session")
    
    
    def del_session(request):
        request.session.flush()
        return HttpResponse('注销了')
    
    

    urls.py

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
    
        url(r'^login/',views.login),
        url(r'^home/',views.home),
        url(r'^index/',views.index),
        url(r'^demo/',views.demo),
        url(r'^logout/',views.logout),
    
        url(r'^set_session/',views.set_session),
        url(r'^get_session/',views.get_session),
        url(r'^del_session/',views.del_session),
    ]
    
    

    html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    </head>
    <body>
    <form action="" method="post">
        <p>username:<input type="text" name="username"></p>
        <p>password:<input type="text" name="password"></p>
        <input type="submit">
    </form>
    </body>
    </html>
    
    
  • 相关阅读:
    python_linux系统相关配置
    python_字典dict相关操作
    python_传参
    mapreduce 学习笔记
    linux 常用命令
    C++ stringstream介绍,使用方法与例子
    C++/C++11中std::numeric_limits的使用
    C++中string erase函数的使用
    C++中accumulate的用法
    malloc的用法和意义
  • 原文地址:https://www.cnblogs.com/WQ577098649/p/12189971.html
Copyright © 2011-2022 走看看