Django学习小记(七)-----Session、Form、文件上传下载

一、用户认证session

1.1 原理

1.1.1基础定义

  • Http特性:HTTP 是一种"无状态"协议,这意味着每次客户端检索网页时,客户端打开一个单独的连接到 Web 服务器,服务器会自动不保留之前客户端请求的任何记录
  • Cookie定义:存储在客户端计算机上(一般是浏览器中)的文本文件,并保留了各种跟踪信息
  • 识别返回用户包括四个步骤:
    • 第一步:浏览器向服务器发送请求
    • 第二步:服务器脚本验证请求,并向浏览器发送一组 Cookie
    • 第三步:浏览器将这些信息存储在本地计算机上,以备将来使用
    • 第四步:当下一次浏览器向 Web 服务器发送任何请求时,浏览器会把这些 Cookie 信息放到request的请求头中发送到服务器,服务器将使用这些信息来识别用户
  • 认证意义:确定当前发过来的请求(request)的人的身份,根据需要每次请求都验证,后续DRF有jwt身份认证,此处session仅作了解即可

1.1.2 session

  • 定义:保存在服务端的键值对,并依托cookie技术实现的用户验证
  • 验证流程
    在这里插入图片描述
  • session存储
    在这里插入图片描述
  • 存储位置:默认为数据库中django_session表中
  • session_key:即为sessionID,以cookie形式发到浏览器保存,验证的关键纽带
  • session_data:保存用户信息,服务端自由设置,并密文保存在表中,用于以后取用
  • expire_date:保存该条记录的过期时间(默认14天)

1.2 代码写法

1.2.1 session配置设置

  • 位置:settings.py中最后一行新增
  • 代码(以下均为默认,只需写修改过的)
    # Session的cookie保存在浏览器上时的key名:默认sessionid
    SESSION_COOKIE_NAME = "sessionid"    
    
    # 是否Https传输cookie:默认否                     
    SESSION_COOKIE_SECURE = False    
    
    # 是否只支持http传输cookie:默认是                       
    SESSION_COOKIE_HTTPONLY = True       
    
    # Session的cookie有效期秒数,从发送时为起算点:默认两周       
    SESSION_COOKIE_AGE = 1209600  
    
    # 是否关闭浏览器时,Session即过期:默认否                        
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False   
    
    # 每次请求是否更新有效期起算点:默认否          
    SESSION_SAVE_EVERY_REQUEST = False                       
    

1.2.2 存储账户的表

  • 文件api/models.py
  • 代码
    from django.db import models
    
    class Account(models.Model):
        name = models.CharField(max_length=24, primary_key=True)
        password = models.CharField(max_length=48)
    
    
  • 表样式
    在这里插入图片描述

1.2.3 视图函数

账户视图函数

  • 位置:api/account.py
  • 功能:用来处理跟账户相关的视图函数
  • 代码
    from django.http import HttpResponse, JsonResponse
    from api import models
    
    
    # 处理注册请求:注册的账号、密码,会被加入到数据库Account表中
    def sign_in(request):
    	# 获取用户输入的账号密码
        name = request.POST.get("name")
        password = request.POST.get("password")
    	
    	# 查询注册的账号是否已在Account表中
        user = models.Account.objects.filter(name=name).first()
        # 若账号不在Account表中,则新增账号,密码
        if not user:
            models.Account.objects.create(name=name, password=password)
            # 此处也可以返回数据给前端做展示或路由跳转
            # 另一种返回 return JsonResponse({"code": True , "mesg": "注册成功"})
            return HttpResponse("注册成功")
        # 若账号在Account表中,则返回数据给前端做展示或路由跳转
        else:
        	# 另一种返回 return JsonResponse({"code": False , "mesg": "用户已存在"})
            return HttpResponse("用户已存在")
    
    
    # 处理登陆请求:会验证账号、密码,并构建session相关
    def log_in(request):
    	# 获取请求的账号、密码
        name = request.POST.get("name")
        password = request.POST.get("password")
    
    	# 查询注册的账号是否已在Account表中
        user = models.Account.objects.filter(name=name).first()
    
    	# 若账号不在Account表中,则返回数据给前端做展示或路由跳转
        if not user:
       		# 另一种返回 return JsonResponse({"code": False , "mesg": "用户不存在"})
            return HttpResponse("用户不存在")
        # 若账号在Account表中,则判断密码,若正确,设置session
        elif password == user.password:
        	# 下一语句执行两步:
        	# 	1、设置django_session表的键值session_key,session_data, expire_data
        	# 	2、服务器将session_key作为cookie传入客户端并写入浏览器
            request.session['user_info'] = {"name": name}
            # 登陆成功,返回数据给前端做展示或路由跳转
            # 另一种返回 return JsonResponse({"code": True , "mesg": "登录成功"})
            return HttpResponse("登录成功")	    
        else:
        	# 用户密码错误,返回数据给前端做展示或路由跳转
        	# 另一种返回 return JsonResponse({"code": False , "mesg": "密码错误"})
            return HttpResponse("密码错误")
    
    
    # 处理登出请求
    def log_out(request):
    	# 删除django_session表的键值session_key,session_data, expire_data
    	# 同时向浏览器发响应,删除浏览器上的cookie
        request.session.flush()  
        # 注销成功
        # 另一种返回 return JsonResponse({"code": True, "mesg": "注销成功"})
        return HttpResponse("注销成功")
    
    
    # 装饰器:在需要登录验证的视图函数上装饰
    def auth_check(func):
    	# 第一参数必须放置request,否则下面的is_login读不出来
        def wrapper_in(request, *argv, **kw):
        	# 获取session中的user_info字段,若未登录则不会存在,设置默认值为False
        	# 读取session具体数据:name = request.session.get("user_info")["name"]
            is_login = request.session.get("user_info", False)
            if not is_login:
            	# 若未登录,直接跳出,返回数据给前端做展示或路由跳转
            	# 另一种返回 return JsonResponse({"code": False , "mesg": "未登陆"})
                return HttpResponse("未登陆")
            # 若已登录,正常执行被装饰的函数      
            return func(request, *argv, **kw)
        return wrapper_in
    

常规视图函数

  • 位置:api/views.py
  • 功能:存常规逻辑视图,需要登录验证的加装饰器
  • 代码
    from django.http import HttpResponse
    from api.account import auth_check
    
    # 登录的用户,可以直接访问到index函数,未登录的用户返回:"未登陆"
    # 返回数据给前端做展示或路由跳转
    @auth_check
    def index(request):
    	# 传字典
    	# return JsonResponse({"code": True , "mesg": "这是主页返回信息"})
    	# 或者传字典式列表,但是要关闭safe选项
    	# return JsonResponse([{"code": True}, {"mesg": "这是主页返回信息"}], safe=False)
        return HttpResponse("这是主页返回信息")
    

1.2.4 账户路由

  • 文件urls.py
  • 代码
    from django.urls import path
    from api import views, account
    
    urlpatterns = [
        path('signin/', account.sign_in),
        path('index/', views.index),
        path('login/', account.log_in),
        path('logout/', account.log_out),
    ]
    

1.3 遇到问题

遇到问题:RuntimeError: ‘cryptography’ package is required for sha256_password or caching_sha2_password auth methods
原因:用mysql数据库会有这个问题,SQLlit3无此问题
解决:pip install cryptography (别挂科学上网软件)

1.4 验证账号路由

  • signin验证
    在这里插入图片描述
  • login验证
    在这里插入图片描述
    在这里插入图片描述
  • logout验证
    在这里插入图片描述
  • 装饰器验证
    在这里插入图片描述

二、表单验证Form

2.1 基础操作

  • Form组件:可以对用户提交的数据进行校验,并返回错误信息与前端交互
  • 代码写法
    文件/api/my_form
    from django.forms import fields, Form				# 用于定义表单验证规则
    from django.http import HttpResponse, JsonResponse	# 用于给前端返回信息
    from api import models								# 用于跟数据库交互
    
    
    class UserForm(Form):
        name = fields.CharField(						# 字符型验证规则
            required=True,      						# 默认,可不写
            min_length=4,								# 最小长度
            max_length=14,								# 最大长度
            error_messages={    						# 定义错误显示别名(对应上面)
                "required": "not null",
                "min_length": "too short",
                "max_length": "too long",
            })
        age = fields.IntegerField(						# 整型验证规则
            required=True,     	 						# 默认,可不写
            min_value=12,								# 最小值
            max_value=60,								# 最大值
            error_messages={    						# 定义错误显示别名(对应上面)
                "required": "not null",
               	"invalid": "form is wrong",				# 格式错误(如果填了字符)
                "min_value": "too young",
                "max_value": "too old",
            })
    
    
    # 路由:http://127.0.0.1:8000/auth/ 会转到这个视图函数
    def check(request):									# 处理验证的视图函数
        obj = UserForm(request.POST)					# 创建UserForm类的对象,并将request.POST传进去
        # 调用UserForm类的基类Form的is_valid方法进行判断加工,返回True或False
        if obj.is_valid():								# 如果通过验证			
            data = obj.cleaned_data						# 获取验证后的数据,data为字典
            # 浏览器传进来的键必须与规则中的键一致,即request中的name和UserForm中的name键名一致
            # 传入的键数目可以大于规则中的键数目
            user_name = request.POST.get('name')	
            # 获取并判断用户是否在数据库中,注意先验证,后拿数据库,可以减小数据库压力
            is_in = models.Account.objects.filter(name=user_name)
            if is_in:
            	# 另一种返回 return JsonResponse({"code": False , "mesg": "用户已存在"})
                return HttpResponse("用户已存在")
            # 用户不在数据库中,则新增
            models.Account.objects.create(name=data['name'], age=data['age'])
            # 另一种返回 return JsonResponse({"code": True, "mesg": "已新增"})
            return HttpResponse("已新增")
        # 未通过验证,则返回所有错误信息obj.errors的Json格式的数据给浏览器
        return HttpResponse(obj.errors.as_json())	
    
  • 路由写法
    文件/main/urls.py
    from django.urls import path
    from api import my_form
    
    urlpatterns = [
        path('auth/', my_form.check),
    ]
    
  • 数据库写法
    文件/api/models.py
    from django.db import models
    
    class Account(models.Model):
        name = models.CharField(max_length=24, primary_key=True)
        age = models.CharField(max_length=48)
    

2.2 验证结果

  • name、age均不满足
    在这里插入图片描述
  • 有一个不满足
    在这里插入图片描述
  • 两者都满足
    在这里插入图片描述
  • 二次新增相同name
    在这里插入图片描述

2.3 验证参数默认值

括号内为基类
继承基类的派生类都具有基类的参数

################# 重要 #####################
Field    
    required=True,               是否允许为空    
    error_messages=None,         错误信息 {'required': '是否可空', 'invalid': '格式错误'}
    show_hidden_initial=False,   是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
    validators=[],               自定义验证规则
    localize=False,              是否支持本地化(用于时间转换)
 
################# 重要 #####################
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插件
 
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,

 
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类型
    ...

三、文件上传下载

3.1 文件上传

3.2 文件下载

上一篇:Django学习小记(六)-----数据库ORM(函数)
下一篇:DRF初识攻坚(一)-----框架初识

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值