flask框架基础分析

flask框架基础分析

web框架原理

1.bs 架构
	bs架构其实就是我们利用socket写的一个服务端
   符合wsgi协议
		WSGI:web Server Gateway Interface ,WSGI不是服务器,也不是python模块,框架,API或者任何软件,他只是一种规范,描述web server如何与web application通信的规范。 是web服务器和web应用程序之间或框架之间的通用接口标准,WSGI就像一座桥梁,WSGI的接口分为两个:一个是web服务器的接口,另一个是与服务器端程序的接口,WSGI的作用就是在协议之间进行转化,WSGI将web组件分成了三类:web服务器(WSGI Server)、Web中间件(WSGI Middleware) 与Web应用程序(WSGI Application)
 		Web Serber接收HTTP请求,封装一系列环境变量,按照WSGI接口标砖调用注册的WSGI application(如:django程序),最后响应返回给客户端。
		虽然WSGI的设计目标是连接标砖的Web服务器(Nginx、Apache)与服务器端程序,但它本身也可以作为web服务器运行。但由于性能方面的限制,该服务器一般只是在测试的时候使用。

2. 使用wsgiref协议
	wsgiref则是官方给出的一个实现了WSGI标准用于演示的简单python内置库,它实现了一个简单的WSGI Server和WSGI Application(在simple_server模块中),主要分为五个模块:simple_server,util,headers,handlers,validate.本质上就是编写一个socket服务端,用于接受用户请求(django)

3.使用werkzeug协议
	werkzeug不是一个web服务器,也不是一个web框架,而是一个工具包,官方的介绍说是一个WSGI工具包,他可以作为一个Web框架的底层库,因为它封装好了很多Web框架的东西,werkzeug本质上就是编写一个socket服务端,勇于接受用户请求(flask)和django中wsgiref是类似的。
  
4.uwsgi
	uwsgi是一种线路协议,是uwsgi服务器独占的协议,用于定义传输信息类型(type of information),每一个 uwsgi packet 前4byte为信息传输类型的描述,与WSGI协议是两种东西。    
	uwsgi是一个web服务器,它实现了WSGI协议。uwsgi、http等协议。Nginx中Httpuwsgimodule的作用是与uwsgi服务器进行交换。django项目部署实际上是uwsgi,他才是web服务器,而不是wsgi。

配置文件写法

项目的配置文件:如果不配,有默认的
几个重要的
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)
    拓展:配置文件都在本地

路由系统

flask 的路由系统,djagno中,路由是单独的urls.py,flask中是装饰的形式

1.使用方式
@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
2.记住:string,int,path
    -methods: 列表,规定请求的方式,如果列表中没有,该请求方式不被支持
    -endpoint:路由别名,如果不写,会以被装饰的函数名作为别名,django中叫name

路由的本质

1.flask中路由是使用装饰器的,但是它的本质其实是app对象(Flask)的方法self.add_url_rule(rule, endpoint, f, **options)

2.如果在视图函数上加了装饰器,其实本质是在调用self.add_url_rule,我们可以不加装饰器,自己调用这个方法,也能完成路由的注册
    
3.路由本质:
    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')


4.其实跟djagno没有大的差距,只是使用装饰器来配置
  • 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>')

flask cbv写法

  • 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方法
  • cbv加装饰器
1.研究第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
  • as_view的执行流程
1.研究第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) 
    
  • 在as_view(name='xxx')中name的作用
1.研究第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')
  • cbv中的methods的作用
# 视图类中还有个类属性 methods = ['POST']
	-用来控制允许的请求方式
    -如果不写,写了什么方法,就允许什么请求

flask 模板语法

1.在我们之前学习的dtl中的所有语法,flask语法都基本支持,并且能够使用,函数的方式进行传参

2.view页面
from flask import Flask, render_template,Markup
app = Flask(__name__)
@app.route('/')
def index():
    # return render_template('test.html', name='joseph', age=19)
    return render_template('test.html',
                           user={
                               1: {'name': 'joseph', 'age': 19, 'hobby': '篮球'},
                               2: {'name': 'sylvia', 'age': 20, 'hobby': '橄榄球'},
                               3: {'name': 'judy', '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()

HTML页面

<!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>
posted @ 2022-12-09 20:38  Joseph-bright  阅读(114)  评论(0编辑  收藏  举报