Flask快速入门(路由、CBV、请求和响应、session)

news2025/1/15 13:11:18

Flask快速入门(路由、CBV、请求和响应、session)

目录

  • Flask快速入门(路由、CBV、请求和响应、session)
    • 安装
    • 创建页面
    • Debug模式
    • 快速使用
    • Werkzeug介绍
    • watchdog介绍
      • 快速体验
    • 路由系统
      • 源码分析
      • 手动配置路由
      • 动态路由-转换器
    • Flask的CBV
      • 快速使用
      • cbv源码分析
    • 请求和响应
      • 请求对象(request)
      • 响应对象
    • Session
      • 基本使用
      • 原理解析

安装

pip install flask

创建页面

from flask import Flask

# 用当前脚本名称实例化Flask对象,方便flask从该脚本文件中获取需要的内容
app = Flask(__name__)

# 配置路由和视图函数的对应关系(基于装饰器)
@app.route("/")
def index():
    return "Hello World!"

# 启动一个本地开发服务器,激活该网页
app.run()
# 或者:
# if __name__ == '__main__':
#     app.run()

Debug模式

终端执行

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

debug模式下:

  • 自动重载 - 根据代码内容变化自动重启项目
  • 终端展示错误提示
  • 日志记录

快速使用

用route接受请求方式

@app.route("/", methods=['GET', 'POST'])
def index():
    return '你好'

直接调用请求方法

@app.get("/")
def index():
    return '你好'

Werkzeug介绍

Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库,它并没有和flask有直接联系,但是flask可以借助它执行各种Web操作,例如Request,Response

from werkzeug.wrappers import Request, Response

@app.route("/")
def index():
    return Response('你好')

watchdog介绍

快速体验

当前目录下修改文件会被监控,并打印日志

import sys
import time
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler

if __name__ == "__main__":
    # 配置日志
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    path = sys.argv[1] if len(sys.argv) > 1 else '.'
    # 初始化监控类(文件的创建 删除...)
    event_handler = LoggingEventHandler()
    # 初始化监控类
    observer = Observer()
    # 配置 observer 以使用 event_handler 来处理 path 路径下的事件,并递归地监控该路径下的所有子目录(由于 recursive=True)
    observer.schedule(event_handler, path, recursive=True)
    # 启动监控
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

路由系统

源码分析

@app.route('/',methods=['GET'])

直接Ctrl左键进入route

@setupmethod
def route(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]:

    # 将视图函数作为参数执行了add_url_rule
    def decorator(f: T_route) -> T_route:
        endpoint = options.pop("endpoint", None)
        self.add_url_rule(rule, endpoint, f, **options)
        return f

    return decorator

image-20240612154416089

该注释的意思是,当有给定的url规则来注册该视图函数时,将会触发该装饰器,且装饰器会执行add_url_rule方法,因此我们只需要搞明白add_url_rule做了什么

@setupmethod
def add_url_rule(
    self,
    rule: str,
    endpoint: str | None = None,
    view_func: ft.RouteCallable | None = None,
    provide_automatic_options: bool | None = None,
    **options: t.Any,
) -> None:
  • rule:定义路由的字符串,例如'/''/login'
  • endpoint:当URL中无参数,函数需要参数时,使用defaults = {‘k’: ‘v’}-为函数提供参数,django中也有,叫kwargs,默认为None
  • view_func:视图函数的名称,也就是源码中的f
  • provide_automatic_options: 一个布尔值,用于控制是否应该自动为路由添加一个 OPTIONS 方法的处理器。如果为 None,则使用应用配置的 ADD_AUTOMATIC_OPTIONS
  • options: 一个可变参数,用于传递额外的选项给路由。这些选项可以包括用于路由的各种配置,如 HTTP 方法的集合(methods

手动配置路由

知晓了路由原理后我们就可以不用装饰器自定义路由

def login():
    return '我是login'

app.add_url_rule('/login', endpoint=None, view_func=login, methods=['GET', 'POST'])

image-20240612161318162

动态路由-转换器

大致与Django同理

# 转换器
app.add_url_rule('/index/<int:pk>')

pk值是一个int类型的任意参数,除此之外还有其他类型参数:

DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}

Flask的CBV

CBV(Class-Based Views)指的是基于类的视图编写方式

快速使用

from flask import Flask, url_for
from flask.views import MethodView

app = Flask(__name__)
app.debug = True

class IndexView(MethodView):
    def get(self):
        return 'get请求'

    def post(self):
        return 'post请求'
    
# name可以理解为别名
app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))

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

# CBV也可以使用路由装饰器:
# @route('/index')  
# class IndexView(MethodView):  

即传了endpoint,又传了name,以谁为准?

  • 如果传了endpoint,以endpoint 为准
    如果没传,以函数名为准,函数名是view,但是被name改了,所以以name为准

cbv源码分析

class View:
    methods: t.ClassVar[t.Collection[str] | None] = None
    provide_automatic_options: t.ClassVar[bool | None] = None
    decorators: t.ClassVar[list[t.Callable[[F], F]]] = []
    init_every_request: t.ClassVar[bool] = True

    def dispatch_request(self) -> ft.ResponseReturnValue:
        raise NotImplementedError()

    @classmethod
    def as_view(
        cls, name: str, *class_args: t.Any, **class_kwargs: t.Any
    ) -> ft.RouteCallable:
        if cls.init_every_request:

            def view(**kwargs: t.Any) -> ft.ResponseReturnValue:
                self = view.view_class(  # type: ignore[attr-defined]
                    *class_args, **class_kwargs
                )
                # 这里其实就是return self.dispatch_request(**kwargs)
                return current_app.ensure_sync(self.dispatch_request)(**kwargs)  # type: ignore[no-any-return]

        else:
            self = cls(*class_args, **class_kwargs)

            def view(**kwargs: t.Any) -> ft.ResponseReturnValue:
                return current_app.ensure_sync(self.dispatch_request)(**kwargs)  # type: ignore[no-any-return]

        if cls.decorators:
            # 将view的名字改为传入的name 否则一直叫view
            view.__name__ = name
            view.__module__ = cls.__module__
            for decorator in cls.decorators:
                view = decorator(view)

        view.view_class = cls  # type: ignore
        view.__name__ = name
        view.__doc__ = cls.__doc__
        view.__module__ = cls.__module__
        view.methods = cls.methods  # type: ignore
        view.provide_automatic_options = cls.provide_automatic_options  # type: ignore
        return view
  • 每当有请求过来时执行view(),执行view的本质就是执行dispatch_request(),self就是我们定义的视图类对象

请求和响应

请求对象(request)

from flask import Flask, request

响应对象

make_response生成的响应对象可以存放字符串、模板、重定向、json

from flask import Flask, render_template, make_response

class ContactView(MethodView):
    def get(self):
        res = make_response('get请求')
        res.set_cookie('name', '<NAME>', path='/contact')
        return res
  • 可以对响应对象添加cookie,path的意思是只有path指定的路径会存储cookie,浏览其他页面不会携带cookie

Session

基本使用

# 配置secret_key 自定义的字符串
app.secret_key = 'abcdefg'
  • session['name'] = '张三'
  • session.pop('name')
  • session.clear()
  • name = session.get('name')

原理解析

  • 存储或修改session时
    • 对session进行加密(三段式)
    • 存储到cookie(obj.set_cookie)
  • 校验session时
    • 根据session取出cookie
    • 将第二段反解放入session中

源码:

# open_session
def open_session(self, app: Flask, request: Request) -> SecureCookieSession | None:
    s = self.get_signing_serializer(app)
    if s is None:
        return None
    val = request.cookies.get(self.get_cookie_name(app))
    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: Flask, session: SessionMixin, response: Response
    ) -> None:
    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)

    # Add a "Vary: Cookie" header if the session was accessed at all.
    if session.accessed:
        response.vary.add("Cookie")

        # If the session is modified to be empty, remove the cookie.
        # If the session is empty, return without setting the cookie.
        if not session:
            if session.modified:
                response.delete_cookie(
                    name,
                    domain=domain,
                    path=path,
                    secure=secure,
                    samesite=samesite,
                    httponly=httponly,
                )
                response.vary.add("Cookie")

                return

            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,
                val,  # type: ignore
                expires=expires,
                httponly=httponly,
                domain=domain,
                path=path,
                secure=secure,
                samesite=samesite,
            )
            response.vary.add("Cookie")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1819595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

你还在手写数据库文档?推荐一款数据库文档生成工具screw

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

【调试笔记-20240612-Linux-在 QEMU 中配置 OpenWrt-23.05 支持访问 Windows 宿主机的共享目录】

调试笔记-系列文章目录 调试笔记-20240612-Linux-在 QEMU 中配置 OpenWrt-23.05 支持访问 Windows 宿主机的共享目录 文章目录 调试笔记-系列文章目录调试笔记-20240612-Linux-在 QEMU 中配置 OpenWrt-23.05 支持访问 Windows 宿主机的共享目录 前言一、调试环境操作系统&…

UEditor文件上传超出大小限制修改无效问题

网上说的方法&#xff0c;试过了&#xff0c;不生效 百度ueditor富文本编辑框怎么设置上传图片大小限制_umeditor 控制图片上传不得超过1m-CSDN博客 直接修改此处

[图解]《分析模式》漫谈02-第2章图的多重性错误

1 00:00:01,400 --> 00:00:02,790 今天&#xff0c;我们来看 2 00:00:04,440 --> 00:00:06,190 分析模式的第2章 3 00:00:06,960 --> 00:00:09,820 一个图上面的一些小问题 4 00:00:13,130 --> 00:00:15,320 第2章的图2.4 5 00:00:16,500 --> 00:00:22,190 …

美丽的拉萨,神奇的布达拉宫

原文链接&#xff1a;美丽的拉萨&#xff0c;神奇的布达拉宫 2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT-3.5&#xff0c;将人工智能的发展推向了一个新的高度。2023年11月7日&#xff0c;OpenAI首届…

Cloudflare 错误 1006、1007、1008 解决方案 | 如何修复

根据不完全统计&#xff0c;使用 Cloudflare 的网站比例已经接近 20%。因此&#xff0c;在日常工作中&#xff0c;比如进行网页抓取时&#xff0c;您可能经常会遇到一些因 Cloudflare 而产生的困难。例如&#xff0c;遇到 Cloudflare 错误 1006、1007 和 1008&#xff0c;这些错…

Windows下基于Frida查看内存基址和修改寄存器

使用Frida能够方便地获取到DLL基址&#xff0c;还能修改寄存器值。首先要通过任务管理器获得进程的PID&#xff0c;然后写Python脚本把Frida附加到这个PID进程&#xff0c;根据IDA分析出来的函数地址&#xff0c;HOOK到目标函数&#xff0c;修改寄存器的值&#xff0c;最终实现…

PHP聚合通多平台支付平台源码

源码介绍 php聚合通多平台支付平台源码&#xff0c;源码搭建了一下&#xff0c;这个源码不复杂&#xff0c;修改一下数据库账号密码然后导入数据库就可以&#xff0c;和网站恢复备份一样简单&#xff01; 源码截图 源码下载 PHP聚合通多平台支付平台源码

vite配置unocss

在vue3vitetseslintprettierstylelinthuskylint-stagedcommitlintcommitizencz-git介绍了关于vitevue工程化搭建&#xff0c;现在在这个基础上&#xff0c;我们增加一下unocss unocss官方文档 具体开发中使用遇到的问题可以参考不喜欢原子化CSS得我&#xff0c;还是在新项目中使…

C++面向对象:多态性

多态性 1.概念 多态性是面向对象的程序设计的一个重要特征。在面向对象的方法中一般是这样表述多态的&#xff1a;向不同的对象发送同一个信息&#xff0c;不同的对象在接收时会产生不同的行为。也就是说&#xff0c;每个对象用自己的方式去响应共同的消息。 2.典例 下面这…

免费个人站 独立站 wordpress 自建网站

制作免费网站 | 免费网站构建器 | WordPress.com https://bioinformatics7.wordpress.com WordPress.com

第2章 Rust初体验5/8:match表达式和模式匹配:更富表达力:猜骰子冷热游戏

讲动人的故事,写懂人的代码 2.5 故事3: 比较答案与点数之和 贾克强:“同学们,我们开始用三种语言来实现故事3吧!” 2.5.1 Rust版故事3 这个故事实在是轻松容易地实现了。赵可菲照着书,一下子就写好了。 @@ -1,4 +1,5 @@use rand::Rng; +use std::cmp::Ordering;use std…

PgSQL技术内幕 - psql与服务端连接与交互机制

PgSQL技术内幕 - 客户端psql与服务端连接与交互机制 简单来说&#xff0c;PgSQL的psql客户端向服务端发起连接请求&#xff0c;服务端接收到请求后&#xff0c;fork出一个子进程&#xff0c;之后由该子进程和客户端进行交互&#xff0c;处理客户端的SQL等&#xff0c;并将结果返…

2024/06/13--代码随想录算法3/17|01背包问题 二维、01背包问题 一维、416. 分割等和子集

01背包问题 二维 卡码网链接 动态规划5步曲 确定dp数组&#xff08;dp table&#xff09;以及下标的含义&#xff1a;dp[i][j] &#xff1a;从下标为[0,i-1]个物品中任取&#xff0c;放进容量为j的背包&#xff0c;价值总和最大为多少。确定递推公式&#xff0c; 有两个方向可…

JVM常用概念之扁平化堆容器

扁平化堆容器是OpenJDK Valhalla 项目提出的&#xff0c;其主要目标为将值对象扁平化到其堆容器中&#xff0c;同时支持这些容器的所有指定行为&#xff0c;从而达到不影响原有功能的情况下&#xff0c;显著减少内存空间的占用&#xff08;理想条件下可以减少24倍&#xff09;。…

使用代理IP常见问题有哪些?

代理IP在互联网数据收集和业务开展中发挥着重要作用&#xff0c;它充当用户客户端和网站服务器之间的“屏障”&#xff0c;可以保护用户的真实IP地址&#xff0c;并允许用户通过不同的IP地址进行操作。然而&#xff0c;在使用代理IP的过程中&#xff0c;用户经常会遇到一些问题…

Uniapp实现页面滚动Tab吸顶,点击tab内容滚动到对应tab内容位置

1.template结构 <view class"content-tabs-box"><view class"content-tabs" :class"{is-fixed: isTabFixed}"><viewv-for"(item, index) in detailTabs" :key"index" class"tab" :class"{act…

pointnet

train_classification.py 把第91行修改为自己的路径&#xff0c;就可以运行了 test_cla.py&#xff0c;需要训练完才能运行测试&#xff0c;我没训练完&#xff0c;所以报错显示我没有best.pth文件 网盘里面是我运行的训练和测试的视频&#xff0c;以及源代码&#xff0c;数…

ROS 自动驾驶多点巡航

ROS 自动驾驶多点巡航&#xff1a; 1、首先创建工作空间&#xff1a; 基于我们的artca_ws&#xff1b; 2、创建功能包&#xff1a; 进入src目录&#xff0c;输入命令: catkin_create_pkg point_pkg std_msgs rospy roscpptest_pkg 为功能包名&#xff0c;后面两个是依赖&a…

新等保2.0防护体系方案

等保2.0防护体系 吉祥学安全知识星球&#x1f517;除了包含技术干货&#xff1a;Java代码审计、web安全、应急响应等&#xff0c;还包含了安全中常见的售前护网案例、售前方案、ppt等&#xff0c;同时也有面向学生的网络安全面试、护网面试等。 最近在写一些咨询相关的材料&…