首页 > 其他分享 >flask基础

flask基础

时间:2022-12-12 20:24:06浏览次数:48  
标签:flask 基础 self request session cookie print app

1 请求与响应

1.1 请求对象

def index():
    # 请求对象,是全局的,需要导入,这个全局的request,在哪个视图函数中,就是当次的request对象,不会乱
    # request.method  提交的方法
    print(request.method)
    # request.args  get请求提及的数据
    print(request.args)
    print(request.args.get('name'))
    # request.form   post请求提交的数据
    print(request.form)
    # request.values  post和get提交的数据总和
    print(request.values)
    # request.cookies  客户端所带的cookie
    print(request.cookies)
    # request.headers  请求头
    print(request.headers)
    print('------')
    # request.path     不带域名,请求路径
    print(request.path)
    # request.full_path  不带域名,带参数的请求路径
    print(request.full_path)
    # request.script_root
    print('服务端:', request.script_root)
    # request.url           带域名带参数的请求路径
    print(request.url)
    # request.base_url        带域名请求路径
    print(request.base_url)
    # request.url_root      域名
    print(request.url_root)
    # request.host_url        域名
    print(request.host_url)
    # request.host            127.0.0.1:500
    print(request.host)
    # request.files
    print(request.files)
    # obj = request.files['files']
    # obj.save('./xx.jpg')

    print(request.data) # django的body
    return 'hellod'

1.2 响应对象

@app.route('/',methods=['GET','POST'])
def index():
    # 1四件套
        # -render_template
        # -redirect
        # -jsonify
        # -''
    # 2写入响应头-->没有响应对象,先做出一个响应对象
    # from .wrappers import Response
    res='helloe'
    res=make_response(res)
    # 往Response的对象中,放入响应头
    res.headers['name']='lqz'
    # 3 写入cookie
    # res.set_cookie('xx','xx')
    res.delete_cookie('xx')
    '''
    key, 键
    value=’’, 值
    max_age=None, 超时时间 cookie需要延续的时间(以秒为单位)如果参数是\ None`` ,这个cookie会延续到浏览器关闭为止
    expires=None, 超时时间(IE requires expires, so set it if hasn’t been already.)
    path=’/‘, Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问,浏览器只会把cookie回传给带有该路径的页面,这样可以避免将cookie传给站点中的其他的应用。
    domain=None, Cookie生效的域名 你可用这个参数来构造一个跨站cookie。如, domain=”.example.com”所构造的cookie对下面这些站点都是可读的:www.example.com 、 www2.example.com 和an.other.sub.domain.example.com 。如果该参数设置为 None ,cookie只能由设置它的站点读取
    secure=False, 浏览器将通过HTTPS来回传cookie
    httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
    '''
    return res

1.3 前后端分离和混合

# 前后端混合,cookie 是后端写入的
    - res.set_cookie('xx','xx') 混合都是这么写的,这样写了,浏览就会把cookie保存到cookie中
    -本质是后端把cookie放到响应头中,浏览器读到响应头中有cookie,把cookie写入到浏览器中
# 前后端分离后
    -直接把客户端要存到cookie中的数据,放到响应体中
    -前端(浏览器,app,小程序),自己取出来,放到相应的位置
        浏览器使用js自己写入到cookie
        app 自己使用代码写入到某个位置

2 session的使用和原理

 

 2.1 session的使用

# 放值 视图函数中
导入全局的session
session['name']='bxf'

# 取值 视图函数中
导入全局的session
print(session['name'])

 

 

2.2 源码分析

# django 的这一套,都在 from django.contrib.sessions.middleware import SessionMiddleware


# flask 在flask源码中
    -请求来了,会执行 app()
    
    
# 整个flask,从请求进来,到请求走的整个流程
    def wsgi_app(self, environ, start_response):
        ctx = self.request_context(environ)
        try:
            try:
                ctx.push() # 它的源码
                response = self.full_dispatch_request()
            except Exception as e:
                error = e
                response = self.handle_exception(e)
            except: 
                error = sys.exc_info()[1]
                raise
            return response(environ, start_response)
        finally:
            ctx.pop(error)
            
            
            
   # ctx.push 的 373行左右    
          if self.session is None:
            session_interface = self.app.session_interface
            self.session = session_interface.open_session(self.app, self.request)
            if self.session is None:
                self.session = session_interface.make_null_session(self.app)
                
   # app.session_interface  就是Flask对象中有个session_interface对象
            SecureCookieSessionInterface()
                -open_session:请求来了,从cookie中取出三段串,反序列化解密放到session中
                -save_session:请求走了,把session字典中的值,序列化加密,放到cookie中
            
            
            
  # open_session:请求来了执行
    def open_session(self, app, request) :
        s = self.get_signing_serializer(app)
        if s is None:
            return None
        # val 就是取出的三段:eyJhZ2UiOiIxOSIsIm5hbWUiOiJscXoifQ.Y5ac9g.vOomQFqFuaqXWqRQhvSNyc61UIk
        val = request.cookies.get('session')
        if not val:
            return self.session_class()
        max_age = int(app.permanent_session_lifetime.total_seconds())
        try:
            data = s.loads(val, max_age=max_age)
            return self.session_class(data)
        except BadSignature:
            return self.session_class()
        
        
  # 请求走了,执行save_session
     def save_session(self, app, session, response):
        name = self.get_cookie_name(app)
        domain = self.get_cookie_domain(app)
        path = self.get_cookie_path(app)
        secure = self.get_cookie_secure(app)
        samesite = self.get_cookie_samesite(app)
        httponly = self.get_cookie_httponly(app)

        if not session:  # 如果视图函数放了,不为空 session['name']='lqz'
            if session.modified:  # 
                response.delete_cookie(
                    name,
                    domain=domain,
                    path=path,
                    secure=secure,
                    samesite=samesite,
                    httponly=httponly,
                )

            return

  
        if session.accessed:
            response.vary.add("Cookie")

        if not self.should_set_cookie(app, session):
            return

        expires = self.get_expiration_time(app, session)
        # 序列化---》加密了
        val = self.get_signing_serializer(app).dumps(dict(session))  # type: ignore
        # 三段:
        response.set_cookie(
            name, # session
            val,  # 三段:
            expires=expires,
            httponly=httponly,
            domain=domain,
            path=path,
            secure=secure,
            samesite=samesite,
        )

        
        
        
        
  # 总结:session的执行流程
    1 请求来的时候,会执行open_session--->取出cookie,判断是否为空,如果不为空,把它反序列化,解密---》字典---》转到session对象中----》视图函数
    
    2 请求走的时候,会执行save_session---->把session转成字典----》序列化加密--》三段---》放到cookie中

3 闪现

# flash 翻译过来叫闪现
# 作用:
    访问a页面,出了错,重定向到了b页面,要在b页面线上a页面的错误信息
    在某个请求中放入值,另一个请求中取出,取出来后就没了
    
# 使用
    设置值:
        flash('不好意思,没有权限看')
        可以用多次
    取值:取出列表
        get_flashed_messages()
        
        
# 使用方式二:分类设置和获取
    设置值:
        flash('钱钱钱',category='lqz')
        flash('666',category='c1')')
        可以用多次
    取值:取出列表
        errors = get_flashed_messages(category_filter=['lqz'])

4 补充异步

# 异步框架 FastAPi
async def index():
    print('sdfasd')
    a++
    await xxx  # io操作
async def goods():   
    pass
# 框架之前的web框架,开启进程,线程---》一条线程会运行多个协程函数----》协程函数中遇到io,读到await关键字,就会切换到别的协程函数


# 一旦使用了异步,以后所有的模块,都要是异步
    -pymysql :同步的
    -redis :同步
    -aiomysql:异步
    -aioredis:异步
    -在fastapi或sanic中,要操作mysql,redis要使用异步的框架,否则效率更低
    -django 3.x 以后页支持async 关键字
    -没有一个特别好异步的orm框架
        -sqlalchemy在做
        -tortoise-orm
        https://tortoise-orm.readthedocs.io/en/latest/index.html
    
    
# aiomysql
import asyncio
import aiomysql

loop = asyncio.get_event_loop()

async def test_example():
    conn = await aiomysql.connect(host='127.0.0.1', port=3306,
                                       user='root', password='', db='mysql',
                                       loop=loop)

    cur = await conn.cursor()
    await cur.execute("SELECT Host,User FROM user")
    print(cur.description)
    r = await cur.fetchall()
    print(r)
    await cur.close()
    conn.close()

loop.run_until_complete(test_example())


# aioredis
import aioredis
import asyncio
class Redis:
    _redis = None
    async def get_redis_pool(self, *args, **kwargs):
        if not self._redis:
            self._redis = await aioredis.create_redis_pool(*args, **kwargs)
        return self._redis

    async def close(self):
        if self._redis:
            self._redis.close()
            await self._redis.wait_closed()


async def get_value(key):
    redis = Redis()
    r = await redis.get_redis_pool(('127.0.0.1', 6379), db=7, encoding='utf-8')
    value = await r.get(key)
    print(f'{key!r}: {value!r}')
    await redis.close()         

if __name__ == '__main__':
    asyncio.run(get_value('key'))  # need python3.7

 

 

5 请求扩展

# 在请求进入视图函数之前,执行一些代码
# 请求出了视图函数以后,执行一些代码
# 类似于django的中间件完成的功能
# 7个装饰器

# 1  before_request:在请求进视图函数之前执行
    多个的话,会从上往下,依次执行, django:process_request
    如果返回四件套之一,就直接返回了
    在这里面,正常使用request对象
    
#2  after_request:在请求从视图函数走之后执行
    多个的话,会从下往上,依次执行, django:process_response一样
    要有参数,和返回值,参数就是response对象,返回值也必须是resposne对象
    session,request 照常使用
    向响应头写东西?向cookie中写东西
    
    
    
# 3 before_first_request:项目启动后,第一次访问会执行,以后再也不执行了
    可以做一些初始化的操作
    
    
# 4 teardown_request:每一个请求之后绑定一个函数,即使遇到了异常,每个请求走,都会执行,记录错误日志
@app.teardown_request
def tear_down(e):
    print(e)  # 如果有异常,这是异常对象
    print('我执行了')
    
    
#5 errorhandler路径不存在时404,服务器内部错误500
# @app.errorhandler(404)
# def error_404(arg):
#     print('404会执行我')
#     # return "404错误了"
#     return render_template('404.html')

@app.errorhandler(500)  # debug为False请情况下才能看到
def error_500(arg):
    print('500会执行我')
    return "服务器内部错误"



# 6  template_global 标签 ,在模板中用  {{sb(1,2)}}
@app.template_global()
def sb(a1, a2):
    return a1 + a2

# 7 template_filter过滤器  在模板中用  {{10|db(1,2)}}
@app.template_filter()
def db(a1, a2, a3):
    return a1 + a2 + a3

6 蓝图

# blueprint:对目录进行划分,因为之前所有代码都写在一个py文件中,后期肯定要分到多个文件中
# 蓝图就是为了划分目录的
# 使用步骤:
    -1 在不同的view的py文件中,定义蓝图
    -2 使用app对象,注册蓝图
    -3 使用蓝图,注册路由,注册请求扩展

# 不用蓝图划分目录
    # 目录结构
    flask_blueprint
        -static  # 静态文件存放位置
        -templates # 模板存放位置
            -user.html # 用户html页面
        -views    # 视图函数的py文件
            -__init__.py # 里面定义了Flask的app对象
            goods.py    # 商品相关视图
            user.py    # 用户相关视图
        app.py         #启动文件
        
# 蓝图小型项目
flask_blueprint_little  # 项目名
    -src                # 项目代码所在路径
        -__init__.py   # app对象创建的地方
        -templates     # 模板
            -user.html
        -static       # 静态文件
        -views        # 视图函数存放位置
            -user.py  # 用户相关视图
            -order.py # 订单相关视图
    -manage.py  # 启动文件


# 大型项目
flask_blurprint_big   # 项目名字
    -src   # 项目代码所在位置
        -__init__.py # src的init,falsk,app实例化
        -settings.py # 配置文件
        -admin       # 类似于django的admin app
            -__init__.py # 蓝图初始化
            -template   # 模板
                -backend.html
            -static   # 静态文件
                -xx.jpg
            -views.py  # 视图层
            -models.py # models层,后期咱们表模型
        -api
            -__init__.py
            -template
            -static
            -models.py
            -views.py
    -manage.py  # 启动文件

 

标签:flask,基础,self,request,session,cookie,print,app
From: https://www.cnblogs.com/shangxin-bai/p/16976990.html

相关文章

  • Unity 脚本基础
    Unity官方手册是最好的教程书,只是偶尔限于冗长ScriptingconceptsAlthoughUnityusesanimplementationofthestandardMonoruntimeforscripting,itstillh......
  • UML 基础: 类图
     ​​UML类图关系大全​​1、关联双向关联:C1-C2:指双方都知道对方的存在,都可以调用对方的公共属性和方法。在GOF的设计模式书上是这样描述的:虽然在分析阶段这种关系是......
  • Python学习基础笔记四十五——包
    OverridetheentrypointofanimageIntroducedinGitLabandGitLabRunner9.4.Readmoreaboutthe extendedconfigurationoptions.Beforeexplainingtheav......
  • 基础算法学习笔记
    #笔记-基础算法快速排序将序列按从小到大或从大到小顺序排序。时间复杂度\(O(nlogn)\),不稳定。步骤确定分界点\(x\):\(q[l]\)、\(q[(l+r)\div2]\),\(q[r]\)、\(......
  • 算法基础课
    给定一个字符串SS,以及一个模式串PP,所有字符串中只包含大小写英文字母以及阿拉伯数字。模式串PP在字符串SS中多次作为子串出现。求出模式串PP在字符串SS中所有......
  • JAVA基础
    JAVA基础注释注释不会被执行,是给写代码的人看的单行注释://多行注释:/**/(快捷键:选中->ctrl+shift+/;/*+回车)文档注释(JavaDoc)(快捷键:/**+回车)......
  • HarmonyOS实战一【JS基础组件】switch、chart等的使用
    写在前面嗯,有这样一个活动,所以搞了一个小Demo,顺便学习一个js的鸿蒙的开发方式,感兴趣的小伙伴积极参与,活动地址:HarmonyOS线上Codelabs系列挑战赛博文主要是一些前端组件使......
  • 关于JAVA 反射 基础知识/编码经验的一些总结
    写在前面温习一下毕业以来学习的东西。准备做成一个系列。所以对于每一部分技术点进行一个笔记整理。更多详见​​java面试的一些总结​​笔记主要是以网上开源的一本​​......
  • 《JAVA8基础应用与开发》读书笔记
    第一章,JAVA技术体系架构JAVASE,(标准版),核心技术。小型桌面应用。 JAVAME,(微型版),嵌入式,电子产品程序。 JAVAEE,(企业版),web应用。涉及的技术面很广。计算机语言机制 ......
  • flask运行后打开的是上一个项目,或者报flask.cli.NoAppException: Could not import 'a
    flask点击红色方框停止运行后,终止了进程。但是端口被反复占用,导致pycharm无法杀掉上一个项目进程,需要手动杀进程。1、打开命令行win+rcmd输入netstat-ano,查看端口......