Django框架10

forms组件之钩子函数

钩子函数的含义其实就是在程序的执行过程中穿插额外的逻辑。

钩子函数之局部钩子(校验单个字段)>>>:校验用户名是否已存在

复制代码
# 局部钩子:校验用户名是否已存在(一次性只能勾一个人)
    '''钩子函数是数据经过了字段第一层参数校验之后才会执行'''
def clean_name(self):  # 自动生成的函数名 专门用于对name字段添加额外的校验规则
        # 1.先获取用户名
        name = self.cleaned_data.get('name')
        # 2.判断用户名是否已存在
        is_exist = models.User.objects.filter(name=name)
        if is_exist:
            # 3.提示信息
            self.add_error('name', '用户名已存在')
        # 4.最后将你勾上来的name返回回去
        return name
复制代码

钩子函数之全局钩子(校验多个字段)>>>:校验密码和确认密码是否一致

复制代码
# 全局钩子:校验密码与确认密码是否一致(一次性可以勾多个人)
def clean(self):
        # 1.获取多个字段数据
        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
复制代码

forms组件字段参数

复制代码
'''
min_length                最小长度
max_length                最大长度
label                     字段名称
error_messages            错误提示
min_value                 最小值
max_value                 最大值
initial                   默认值
validators                正则校验器
'''
复制代码
复制代码
from django.core.validators import RegexValidator
  phone = forms.CharField(
        validators=[
                    RegexValidator(r'^[0-9]+$', '请输入数字'),
                    RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
    )
widget                        控制渲染出来的标签各项属性
    password = forms.CharField(                          widget=forms.widgets.PasswordInput(attrs={'class':'form-control'})
)
  forms.widgets.控制type的类型(attrs=控制各项属性:class id ...)
choices                        选择类型的标签内部对应关系
    可以直接编写 也可以从数据库中获取
      hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    )
    def __init__(self, *args, **kwargs):
        super(MyForm,self).__init__(*args, **kwargs)
        self.fields['hobby'].choices = models.Classes.objects.all().values_list('id','caption')
复制代码

Forms组件源码分析

复制代码
def is_valid(self):
    return self.is_bound and not self.errors
# 查看类源码发现只要给类传参self.is_bound肯定是True

@property
def errors(self):
       if self._errors is None:
       self.full_clean()
    return self._errors
# 查看了源码发现self._errors初始化就是None 所以肯定走full_clean方法

# 查看源码发现校验数据的整个过程内部都有异常处理机制
from django.core.exceptions import ValidationError
raise ValidationError('用户名不存在 你个DSB')
复制代码

ModelForm简介

forms组件主要配合models里面的默写类一起使用,但是默写类里面的字段需要在forms类中相当于重写一遍,代码冗余;
为了更好的结合forms与models的关系,有了一个ModelForm(基于forms组件)。

复制代码
class MyUser(forms.ModelForm):
    class Meta:
        model = models.User  # 指定关联的表
        fields = '__all__'  # 所有的字段全部生成对应的forms字段
        labels = {
            'name': '用户名',
            'age': '年龄',
            'addr': '地址',
            'email': '邮箱'
        }
        widgets = {
            "name": forms.widgets.TextInput(attrs={"class": "form-control"}),
        }


def reg(request):
    form_obj = MyUser()
    if request.method == 'POST':
        form_obj = MyUser(request.POST)
        if form_obj.is_valid():
            # form_obj.save()  # 新增数据
            edit_obj = models.User.objects.filter(pk=5).first()
            form_obj = MyUser(request.POST, instance=edit_obj)  # 是新增还是保存就取决于有没有instance参数
            form_obj.save()  # 编辑数据
    return render(request, 'reg.html', locals())
复制代码

 

cookie简介

  • cookie简介:

前端浏览器以明文形式存放的具有key、value信息特征的字符串。

  • cookie的作用:

在前后台均可以访问并设置cookie,从而解决HTTP协议的无状态特点导致先后两次请求无逻辑可寻问题(如:不同用户登录后,再进入个人主页,明显是有信息区别的)。

  • cookie使用:

随着浏览器的发展,很多浏览器不再对cookie个数加以限制,但仍存在大小的限制,一般为4k;但为了达到传输的高效,服务器的解析速度,还是建议开发者严格控制cookie个数。

  • cookie本质:

指代服务端让客户端保存的数据(存储在客户端上与用户信息相关的数据);为页面文档document的一个字节属性:document.cookie = 'key=value;'。

Django操作cookie:

复制代码
# Django用HttpResponse对象操作Cookie
response = HttpResponse('所有的响应都是HttpResponse对象')
# 设置cookie:key、vaule与过期时间
response.set_cookie(key, value, max_age)
# 删除cookie:key
response.delete_cookie(key)
# 设置加盐cookie:key、vaule与盐字符串(就是简易的加密)
response.set_signed_cookie(key, value, salt)

# 通过request对象获取Cookie
# 获取key对应的value
request.COOKIES.get(key, None)
# 获取加盐后的key对应的value
request.get_signed_cookie(key, salt)

'''
了解:set_cookie方法的其他参数
1. expires:过期时间,格式为字符串类型的时间
2. path:作用路径,/代表所有路径下均起作用
3. domain:作用域名
4. secure:布尔类型,浏览器是否通过HTTPS方式回传cookie
5. httponly:布尔类型,JS能否直接访问该条cookie
'''
复制代码

cookie运用:

复制代码
'''
1. /index/访问主页(可直接访问),主页中存在四个转跳
    -- 登录(/login/)
    -- 个人主页(/user/)
    -- 订单详情(/order/)
    -- 注销(/logout/)
2. 进入个人主页、订单详情页面时,如果未登录,需先登录,然后自动回到个人主页或订单详情页面,反之直接进入
'''
# views.py
from django.shortcuts import render, redirect, HttpResponse

# 确认登录装饰器
def login_check(func):
    def inner(request, *args, **kwargs):
        is_login = request.COOKIES.get('is_login', False)
        # 确定当前被装饰的请求,登录完毕可以跳转回去
        url = request.get_full_path()
        if is_login:
            return func(request, *args, **kwargs)
        else:
            # 将回跳的路径作为参数(登录的表单action需要空着不写)
            return redirect('/login/?back_url=%s' % url)
    return inner

# 主页
def index(request):
    return render(request, 'index.html')

# 登录页面
def login(request):
    if request.method == "GET":
        return render(request, 'login.html')
    if request.method == "POST":
        # 获取回跳的地址
        back_url = request.GET.get('back_url', '/index/')
        usr = request.POST.get('usr', None)
        pwd = request.POST.get('pwd', None)
        if usr == 'abc' and pwd == '123':
            # 确定回跳
            response = redirect(back_url)
            # 登录成功获取cookie
            for i in range(500):
                response.set_cookie('usr%i' % i, usr)
            response.set_cookie('is_login', True)
            return response

@login_check
def order(request):
    print(request.COOKIES)
    usr = request.COOKIES.get('usr', None)
    return render(request, 'order.html', locals())

@login_check
def user(request):
    usr = request.COOKIES.get('usr', None)
    return render(request, 'user.html', locals())

def logout(request):
    response = HttpResponse('注销成功')
    response.delete_cookie('is_login')
    response.delete_cookie('usr')
    return response
复制代码

session简介

  • session简介:

早期的cookie是直接存储的用户明文相关信息,数据信息不安全;因此为了弥补cookie的缺陷,引入了session。

  • session原理:

在后台通常以密文形式存放key、value形式数据,一个会话存放为数据库的一条字段。

用户登录成功之后,服务端生成一个随机字符串,返回给客户端保存;之后客户端每次发请求携带该随机字符串,服务端获取之后比对后台数据。

ps:

session的工作必须依赖于cookie。

客户端也有权拒绝保存数据。

  • session的作用:

结合cookie使用,解决cookie的不安全性。

  • session本质:

session是存放在服务器端的key-value形式的状态数据;即指代服务端保存的跟用户信息相关的数据。

Django操作session:

复制代码
# 操作方法
# 1. 设置
request.session['key1'] = 'value1'
request.session['key2'] = 'value2'
# 过程:
# i) 生成一个随机字符串,作为主键
# ii) 在django_session表中插入有三个字段的一条数据(一条数据对应一个浏览器会话)
    -- session_key:主键-随机字符串
    -- session_data:该会话拥有的所有key-value形成的大字典的加密字符串
    -- expire_date:过去时间,默认14天
# iii) 往浏览器中写入一条cookie,sessionid=主键的随机字符串

2. 获取
request.session.get('key', None)

3. 删除
request.session.delete()  # 只删除当前会话对应的一条记录
request.session.flush()  # 除了删除当前会话对应的一条记录外,还删除对应浏览器中的cookie

5. 其他
request.session.session_key  # 获取当前会话对应的session_key
request.session.exists('session_key')  # 判断某session_key是否存在
request.session.clear_expired()  # 情况所有过去的Session
复制代码

Django操作session补充

复制代码
request.session.session_key  # 获取产生的随机字符串
request.session.delete()  # 只删客户端
request.session.flush()  # 服务端 客户端都删
request.session.set_expiry(value)  # 设置超时时间
    * 如果value是个整数,session会在些秒数后失效。
    * 如果value是个datatime或timedelta,session就会在这个时间后失效。
    * 如果value是0,用户关闭浏览器session就会失效。
    * 如果value是None,session会依赖全局session失效策略。
  
针对session数据的存储位置 有五种方案
    1.数据库存储
  2.缓存存储
  3.文件存储
  4.缓存+数据库存储
  5.动态加密
复制代码

 

posted @   *sunflower*  阅读(73)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示