Flask入门
1 Flask介绍
# 目前python界,比较出名的web框架 -django:大而全,web开发用的东西,它都有 -Flask:小而精,只能完成请求与响应,session,cache,orm,admin。。。统统没有 -很多第三方框架,flask完全可以变成django -----同步框架----- django从3.x 改成了异步框架 ----以下是异步框架-------- -Tornado:非常少了,ptyhon2.x上,公司里用的多一些 -Sanic : python 3.6 及以上 -FastAPI # Flask Flask是一个基于Python开发并且依赖jinja2模板(模板语言)和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。 “微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。 默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用
2 Flask快速使用
# pip3 install flask # 最新2.2.2 from flask import Flask app = Flask(__name__) # 注册路由 @app.route('/index') def index(): return '你看到我了' if __name__ == '__main__': app.run(host='127.0.0.1',port=8080)
3 配置文件写法
# 项目的配置文件:如果不配,有默认的 # 几个重要的 # DEBUG:是否是调试模式 # SECRET_KEY:项目的秘钥 # print(app.config) # 1 使用配置文件之一:(写小脚本测试阶段用)直接通过app对象,配置上,只能配置几个,本质都要放到app.config中 # app.debug=True # app.secret_key='asdfasf4555' # app.session_cookie_name='sss' # print(app.config) # 2 直接通过app.config 配置 # app.config['DEBUG'] = True # app.config['SECRET_KEY'] = 'asfasdf' # print(app.config) # 3 通过配置文件(很像djagno),不常用 # app.config.from_pyfile('settings.py') # print(app.config) # 4 通过类配置(用的多,可以有多套配置) # app.config.from_object('setting.DevelopmentConfig') # app.config.from_object('setting.ProductionConfig') # print(app.config) # 5 以下,做了解 # app.config.from_envvar("环境变量名称") # app.config.from_json("json文件名称") #使用分布式配置中心 import requests res=requests.get('asdfasdfasdf').json() app.config.from_mapping(res) # 拓展:配置文件都在本地
4 路由系统
# flask 的路由系统,djagno中,路由是单独的urls.py,flask中是装饰的形式 # 使用方式 @app.route:重要的参数 -rule: 字符串的路径,使用转换器 <string:name> <name> 'default': UnicodeConverter, 'string': UnicodeConverter, 'any': AnyConverter, 'path': PathConverter, # /xx/sss/ 'int': IntegerConverter, # 数字 'float': FloatConverter, #小数 'uuid': UUIDConverter, #asdfas-asdfas-asdf #记住:string,int,path -methods: 列表,规定请求的方式,如果列表中没有,该请求方式不被支持 -endpoint:路由别名,如果不写,会以被装饰的函数名作为别名,django中叫name
5 路由本质
def route(self, rule, **options): def decorator(f): endpoint = options.pop("endpoint", None) self.add_url_rule(rule, endpoint, f, **options) return f return decorator
# flask中路由是使用装饰器的,但是它的本质其实是app对象(Flask)的方法self.add_url_rule(rule, endpoint, f, **options) # 如果在视图函数上加了装饰器,其实本质是在调用self.add_url_rule -我们可以不加装饰器,自己调用这个方法,也能完成路由的注册 # 路由本质: ''' 1 @app.route('/') 先执行完成,结果是decorator内层函数 @decorator def index(): 2 index=decorator(index) def decorator(f): # @app.route('/',endpoint='index') 如果没有传endpoint,这个地方就是None endpoint = options.pop("endpoint", None) # self是Flask的对象,app :rule路由, endpoint:别名,是None,其他的打散了传入了(methods..) self.add_url_rule(rule, endpoint, f, **options) return f 3 加了装饰器最终,返回的还是index,只不过执行了 self.add_url_rule(rule, endpoint, f, **options) 4 Flask类中得add_url_rule方法 -rule:就是装饰器传入的路径,路由 -endpoint:别名 -view_func:视图函数不加括号 5 得到的结论,现在不需要使用装饰器来注册路由了,自己写 app.add_url_rule('/home', view_func=home, endpoint='home') ''' # 其实跟djagno没有大的差距,只是使用装饰器来配置
5.1 add_url_rule的参数
@app.route和app.add_url_rule参数: # rule, URL规则 # view_func, 视图函数名称 # defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'} 为函数提供参数,就是djagno中得kwargs # endpoint = None, 名称,用于反向生成URL,即: url_for('名称'),等同于django的reverse # methods = None, 允许的请求方式,如:["GET", "POST"] # strict_slashes 对URL最后的 / 符号是否严格要求 strict_slashes = None ''' @app.route('/index', strict_slashes=False) #访问http://www.xx.com/index/ 或http://www.xx.com/index均可 @app.route('/index', strict_slashes=True) #仅访问http://www.xx.com/index ''' # redirect_to 重定向到指定地址 redirect_to = None, ''' @app.route('/index/<int:nid>', redirect_to='/home/<nid>') '''
6 cbv写法
6.1 flask 的cbv写法
# 第一步:写一个类,继承MethodView class Login(MethodView): def get(self): return '我是get' def post(self): return '我是psot' # 第二步:注册路由 name 是别名,本质就是endpoint app.add_url_rule('/login', view_func=Login.as_view(name='index')) # 第三步:只要向 /login 发送get请求,就会执行Login 的get方法
6.2 cbv加装饰器
# 研究第0个问题:cbv加装饰器,如何做? 类属性中加入,加入decorators = [auth, ],属性是一个列表,按照列表顺序,依次给每个方法加装饰器 def as_view(cls, name, *class_args, **class_kwargs ) : .... if cls.decorators: for decorator in cls.decorators: ''' # 装饰器原理: @auth def view(): 本质是 view=auth(view) ''' # 给view加装饰器----》给视图类中得方法加装饰器 view = decorator(view) return view
6.3 as_view的执行流程
# 研究第1个问题,as_view的执行流程 def as_view(cls, name, *class_args, **class_kwargs): def view(**kwargs): return self.dispatch_request(**kwargs) return view -请求来了,路由匹配成功,会执行as_view内的view()----》self.dispatch_request---》MethodView的dispatch_request -MethodView的dispatch_request def dispatch_request(self, **kwargs): # 在当前视图类中反射,请求方式的小写字符串(get),我们写了get方法 meth = getattr(self, request.method.lower(), None) # 执行get() return meth(**kwargs)
6.4 Login.as_view(name='index')
# 研究第2个问题:Login.as_view(name='index') name到底有什么用,还必须传 -先研究 endpoint 有什么用,正常的fbv,如果不写endpoint,会以函数名作为别名,endpoint如何设置的 -如果endpoint为None,它把函数名作为了endpoint if endpoint is None: endpoint = _endpoint_from_view_func(view_func)# view_func.__name__ options["endpoint"] = endpoint -Login.as_view(name='index'),name到底有啥用 -app.add_url_rule('/login', view_func=Login.as_view('login')) -没有传endpoint,Login.as_view('login')是 view函数的内存地址, -endpoint会以函数名作为endpoint的值,现在所有函数都是view,必须传入name,来修改调view函数的名字 -如果传了endpoint,别名以endpoint为主,如果不传endpoint,别名以name为主 app.add_url_rule('/login', view_func=Login.as_view(name='login'),endpoint='xxx')
6.5 继承View写cbv
# 继承View写视图类(CBV) -1 继承 View 的视图类,执行流程都是一样的 -2 请求来了,路由匹配成功,执行self.dispatch_request -3 self.dispatch_request 没有实现,直接抛异常NotImplementedError() -4 必须重写 dispatch_request,自己写匹配规则,执行不同的方法
6.6 cbv中得methods作用
# 视图类中还有个类属性 methods = ['POST'] -用来控制允许的请求方式 -如果不写,写了什么方法,就允许什么请求
7 模板语法
from flask import Flask, render_template,Markup app = Flask(__name__) @app.route('/') def index(): # return render_template('test.html', name='lqz', age=19) # return render_template('test.html', # user={ # 1: {'name': 'lqz', 'age': 19, 'hobby': '篮球'}, # 2: {'name': 'lqz1', 'age': 20, 'hobby': '橄榄球'}, # 3: {'name': 'lqz2', 'age': 21, 'hobby': '乒乓球'}, # }) a='<a href="http://www.baidu.com">点我看美女</a>' # a=Markup(a) return render_template('test.html',a=a) if __name__ == '__main__': app.run()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {#{{ name }}---{{ age }}#} {#<table>#} {# {% for k,v in user.items() %}#} {# <tr>#} {# <td>{{ k }}</td>#} {# <td>{{ v.name }}</td>#} {# <td>{{ v['name'] }}</td>#} {# <td>{{ v.get('name') }}</td>#} {# <td><a href="/detail/{{ k }}">查看详细</a></td>#} {# </tr>#} {# {% endfor %}#} {#</table>#} {#<table>#} {# {% if name %}#} {# <h1>Hello {{ name }}!</h1>#} {# {% else %}#} {# <h1>Hello World!</h1>#} {# {% endif %}#} {#</table>#} {#{{ a|safe }}#} {{ a}} </body> </html>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)