day04

内容概要

  • 请求上下文分析(源码request原理)
  • wtforms(了解)

补充

导出项目依赖

之前 pip freeze > requirements.txt把当前解释器环境下的所有第三方依赖都导出来

使用第三方模块,更精确的导出依赖pipreqs

第一步:安装 pip install pipreqs

第二步:使用命令,导出项目依赖pipreqs ./

​ win由于编码问题可能会出错:pipreqs ./ --encoding=utf8

image-20230406154537612

image-20230406154645256

​ mac,linx没有问题

第三步:就会在项目根路径下生成:requirements.txt

函数和方法

只要会自动传值,就是方法,函数,有几个值就要传几个值,否则报错

函数就是普通函数,有几个参数就要传几个参数

方法:绑定给对象的方法,绑定给类的方法,绑定给谁的,有谁来调用,会自动把自身传入

类的绑定方法,对象可以来调,会自动把类传入

对象的绑定方法:类可以来调用,但是它就是普通函数。有几个参数就需要传几个参数

MethodType检查一个对象, 是不是方法
FunctionType检查一个对象,是不是函数
isinstance 判断 一个对象, 是不是一个类的对象
issubclass 判读一个类,是不是另一个类的子类
from types import MethodType, FunctionType


# isinstance
# issubclass
class A:
    pass


class B(A):
    pass


obj = A()
obj1 = B()

# print(isinstance(obj, A))  # True
# print(isinstance(obj1, A))  # True
# print(type(obj) == A)  # True
# print(type(obj1) == A)  # False

# class C:
#     pass
#
#
# print(issubclass(B, A))  # True
# print(issubclass(A, A))  # True
# print(issubclass(C, A))  # False

判断函数和方法

from types import MethodType, FunctionType
class A:
    def aa(self):
        pass

    @classmethod
    def bb(cls):
        pass
    @staticmethod
    def cc():
        pass

def add():
    pass

# 判断对象调用 aa, bb, cc,
# obj = A()
# print(isinstance(obj.aa, MethodType))  # True 对象调用一个绑定给对象的方法, 该方法就是方法
# print(isinstance(obj.bb, MethodType))  # True 对象调用一个绑定给类的方法, 该方法就是方法
# print(isinstance(obj.cc, MethodType))  # False 对象调用一个静态方法, 该方法是 普通函数
#
# print(isinstance(obj.aa, FunctionType))
# print(isinstance(obj.bb, FunctionType))
# print(isinstance(obj.cc, FunctionType))

# 判断类调用 aa, bb, cc,


# print(isinstance(A.aa, MethodType))  # False 类调用一个绑定给对象的方法, 该方法变成了普通函数
# print(isinstance(A.bb, MethodType))  # True 类调用一个绑定给类的方法, 该方法就是方法
# print(isinstance(A.cc, MethodType))  # False 类调用一个静态方法, 该方法是 普通函数
#
# print(isinstance(A.aa, FunctionType))
# print(isinstance(A.bb, FunctionType))
# print(isinstance(A.cc, FunctionType))

print(isinstance(add, FunctionType))  # True

总结:只要会自动传值,就是方法,函数,有几个值就要传几个值,否则报错

threading.local对象

local对象

并发编程时,多个线程操作同一个变量,会出现并发安全问题,咱们需要加锁

使用local对象,多线程并发操作时,不需要加锁,不会出现数据错乱threading.local

其他语言也有这个东西ThreadLocal,java中面试会被经常问到,python没人问

本质原理:
多个线程修改同一个数据,复制多份变量每个线程用,为每个线程开辟一块空间进行数据存储

每个线程都有自己那部分数据

image-20230406163355012

但是我睡2s后

# import time
# from threading import Thread, get_ident
# lqz = ""
# def task(i):
#     global lqz
#     lqz = i
#     print(lqz,"前")
#     time.sleep(2)
#     print("线程%s" % get_ident(), lqz)
# if __name__ == '__main__':
#     for i in range(10):
#         Thread(target=task, args=(i,)).start()

image-20230406163644875

使用local方法

# import time
# from threading import Thread, get_ident, local
# l = local()
# def task(i):
#     global lqz
#     l.a = i
#     time.sleep(2)
#     print("线程%s" % get_ident(), l.a)
# if __name__ == '__main__':
#     for i in range(10):
#         Thread(target=task, args=(i,)).start()

image-20230406164200347

多个线程修改同一个数据,复制多份变量每个线程用,为每个线程开辟一块空间进行数据存储

每个线程都有自己那部分数据

偏函数

def add(a, b, c):
    return a + b + c




# add(2)  # 直接报错
# 现在只有一个参数, 后面的俩参数,需要过一会才知道
# 借助与偏函数,先提前给它把第一个参数传入,后面知道了
# 后面俩参数,在传后面俩
add = partial(add, 2)  # 先传一个参数

print(add(3, 4))

image-20230406164917771

flask整个生命执行流程(1.1.4版本为例)

储备

image-20230406170106407


image-20230406165450952

image-20230406165823075

image-20230406170438311

image-20230406170518647

image-20230406170659819

image-20230406170856620

image-20230406171042111

image-20230406171318113

我们回到 Flask的 wsgi_app方法中继续往下走

image-20230406171631884

image-20230406171756958

image-20230406171822459

image-20230406171926810

image-20230406172408645

image-20230406174113733

我们在回到RequestContext的push方法中

image-20230406173237681

{"id":{"stack":[app_cotext,request_context]}}

image-20230406173910895

wtforms

django有forms组件

  • 生成前端模板
  • 校验数据
  • 渲染错误信息

flask中使用第三方的wtforms实现像django的forms一样的功能

  1. 导入,定义一个类,继承forms
  2. 模板中,for循环生成模板
  3. 视图函数中,使用form检验数据

py

from flask import Flask, render_template, request, redirect
from wtforms import Form
from wtforms.fields import simple
from wtforms import validators
from wtforms import widgets

app = Flask(__name__, template_folder="templates")

app.debug = True


class LoginForm(Form):
    # 字段
    name = simple.StringField(
        label="用户名",
        validators=[
            validators.DataRequired(message="用户名不能为空"),
            validators.Length(min=6, max=18, message="用户名长度必须大于%(min)d且小于%(max)d"),
        ],
        widget=widgets.TextInput(),  # 页面上显示的插件
        render_kw={"class": 'form-control'}
    )
    pwd = simple.PasswordField(
        label="密码",
        validators=[
            validators.DataRequired(message="密码不能为空"),
            validators.Length(min=6, max=18, message="密码长度必须大于%(min)d且小于%(max)d"),
            validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}",
                              message="密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符")
        ],
        widget=widgets.PasswordInput(),  # 页面上显示的插件
        render_kw={"class": 'form-control'}
    )


@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "GET":
        form = LoginForm()
        return render_template('login.html', form=form)
    form = LoginForm(formdata=request.form)
    if form.validate():
        print("用户提交数据通过格式校验的值为:", form.data)

    return render_template("login.html", form=form)


if __name__ == '__main__':
    app.run()

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="post">
    <p>{{form.name.label}}: {{form.name}} {{form.name.errors[0] }}</p>

    <p>{{form.pwd.label}} {{form.pwd}} {{form.pwd.errors[0] }}</p>
    <input type="submit" value="提交">
</form>
</body>
</html>

image-20230406215812240

image-20230406215904444

去除前端的校验

image-20230406215934559

image-20230406220042285

posted @ 2023-04-06 22:04  可否  阅读(42)  评论(1)    收藏  举报