• 11.2 Flask 配置文件,路由系统


    配置文件系统

    构建 Flask 应用时指定

    app = Flask(
       __name__,
       template_folder = '',  # 指定存储模板文件夹名称
       static_url_path = '',  # 指定静态文件访问路径
       static_folder = '',   # 指定存储静态文件的文件夹名称
    )

    一般不推荐修改此配置. 默认的配置即可

    启动程序时指定运行配置

    app.run(
      debug = True,    # 调试模式
      port = 8888      # 端口
      host = '0.0.0.0'  # 指定能够访问到本项目的ip地址,不设置此的话只能自己和自己玩
    )

    自定义配置文件

    创建一个 setting.py 用于存放配置文件的相关属性

    配置文件中可以进行分级继承来区分不同视图的配置文件设置

    默认配置文件放在项目根路径下

    # settings.py
        
        class Base(object):    # 所有的都要有用到的配置更改 
            TEST = True
    
        class Dev(Base):
            DEV = True
    
        class Pro(Base):
            PRO = True 

    配置文件的设置方式

    常用的是以下三种

    # 方式1 直接更改
    app.config["要更改的字段"] = True  
     
    # 方式2 指定对象方式 # app.config.from_object("settings.Dev") # 通过另外指定配置文件来保存更改 app.config.from_object("settings.Pro") # 可以指定多套配置文件随意切换

    # 方式3 指定文件方式
    app.config.from_pyfile("settings.py") # 通过配置文件名来
    # PS: 从sys.path中已经存在路径开始写
     

    默认的配置文件

    flask中的配置文件是一个flask.config.Config对象(继承字典),默认的配置如下

       'DEBUG':                                get_debug_flag(default=False),  是否开启Debug模式
        'TESTING':                              False,                          是否开启测试模式
        'PROPAGATE_EXCEPTIONS':                 None,                          
        'PRESERVE_CONTEXT_ON_EXCEPTION':        None,
        'SECRET_KEY':                           None,
        'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),
        'USE_X_SENDFILE':                       False,
        'LOGGER_NAME':                          None,
        'LOGGER_HANDLER_POLICY':               'always',
        'SERVER_NAME':                          None,
        'APPLICATION_ROOT':                     None,
        'SESSION_COOKIE_NAME':                  'session',
        'SESSION_COOKIE_DOMAIN':                None,
        'SESSION_COOKIE_PATH':                  None,
        'SESSION_COOKIE_HTTPONLY':              True,
        'SESSION_COOKIE_SECURE':                False,
        'SESSION_REFRESH_EACH_REQUEST':         True,
        'MAX_CONTENT_LENGTH':                   None,
        'SEND_FILE_MAX_AGE_DEFAULT':            timedelta(hours=12),
        'TRAP_BAD_REQUEST_ERRORS':              False,
        'TRAP_HTTP_EXCEPTIONS':                 False,
        'EXPLAIN_TEMPLATE_LOADING':             False,
        'PREFERRED_URL_SCHEME':                 'http',
        'JSON_AS_ASCII':                        True,
        'JSON_SORT_KEYS':                       True,
        'JSONIFY_PRETTYPRINT_REGULAR':          True,
        'JSONIFY_MIMETYPE':                     'application/json',
        'TEMPLATES_AUTO_RELOAD':                None,

    视图函数取配置

    要想在视图函数中获取配置文件的值,都是通过app.config来拿。

    但是如果视图函数和Flask创建的对象app不在一个模块。就得导入来拿。

    可以不用导入,直接导入一个current_app,这个就是当前的app对象,用current_app.config就能查看到了当前app的所有的配置文件

    from flask import Flask,current_app
    @app.route('/index',methods=["GET","POST"])
    def index():
        print(current_app.config)   #当前的app的所有配置
        session["xx"] = "fdvbn"
        return "index"

    路由系统

    FBV 的路由添加方式

    语法

    @app.route(参数)

    可选参数

    rule

    设置动态路由,路径中可以带参数 ,必须要指定类型

    /index/<int:nid>

    仅允许的类型 

    • string 字符串
    • float 浮点型
    • path 路径
    • int 整型
    • any 任何
    • uuid uuid类型

    默认的不支持正则路由匹配的

    默认不指定的时候按str 处理

    实例

    from flask import Flask
    
    # 将当前的运行的主程序构建成 Flask 应用, 以便去接受用户的请求和响应
    app = Flask(__name__)
    
    
    # 路由定义, 目的是为了匹配用户的访问路径
    # "/" 表示整个网站的根 " index " 表示自定义的访问路径
    # index() 表示匹配上访问路径后的处理程序( views ), 此函数必须要有返回值 ( 字符串 / 模板文件 )
    @app.route('/index')
    def index():
        return "<h1> 这是我的网站的首页 </h1>"
    
    
    # 无参数
    @app.route('/')
    def first():
        return "This is my first flask demo"
    
    
    # 单参数
    @app.route('/name/<name>')
    def name(name):
        return "This is {0} first flask".format(name)
    
    
    # 带类型的参数
    @app.route('/num/<int:num>')
    def num(num):
        return "get a unm: {0} ".format(num)
    
    
    """
    可选的参数类型
        str:    字符串,不能加 "/" 
        int:    整数
        float:  浮点型
        path:   路径,本质还是字符串, 但是可以加 "/" 
            不推荐使用 path 容易误解
     """
    
    
    # 多参数
    # str 类型不需要加 <str:...>
    @app.route('/more/<name>/<int:age>')
    def more(name, age):
        return " name : {name} ; age: {age}".format(name=name, age=age)
        # return "name: %s ; age : %s" % (name, age)
    
    
    if __name__ == '__main__':
        # debug = True  # 调试模式, 部署运行是设置为 False
        app.run(debug=True)  # 启动程序

    多 URL 的路由匹配方式

    允许多个路由匹配到同一个 视图上

    @app.route('/manyA/')
    @app.route('/manyB/')
    @app.route('/manyC/')
    def many():
        return "我可以匹配多个URL , 厉害吧"

    URL 中适配正则的验证方式

    from flask import Flask,url_for
    
        app = Flask(__name__)
    
        # 定义转换的类
        from werkzeug.routing import BaseConverter
        class RegexConverter(BaseConverter):
            """
            自定义URL匹配正则表达式
            """
    
            def __init__(self, map, regex):
                super(RegexConverter, self).__init__(map)
                self.regex = regex
    
            def to_python(self, value):
                """
                路由匹配时,匹配成功后传递给视图函数中参数的值
                :param value: 
                :return: 
                """
                return int(value)
    
            def to_url(self, value):
                """
                使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
                :param value: 
                :return: 
                """
                val = super(RegexConverter, self).to_url(value)
                return val
    
        # 添加到converts中
        app.url_map.converters['regex'] = RegexConverter
    
        # 进行使用
        @app.route('/index/<regex("d+"):nid>',endpoint='xx')
        def index(nid):
            url_for('xx',nid=123)  #反向生成,就会去执行to_url方法
            return "Index"
    
        if __name__ == '__main__':
            app.run()

    default 添加默认值示例

    from flask import Flask
    
    app = Flask(__name__)
    
    # 2. 函数index需要参数,但是url里无参数,即可以用defaults={"k":"v"}为函数提供参数
    @app.route("/",methods=['GET','POST'],defaults={"nid":888})
    # 1. 函数index需要参数,但是url里无参数
    def index(nid):
        print(nid)      # 会在工作它打印nid   888
        return "Hello World!"
    
    if __name__ =="__main__":
        app.run()

    strict_slashes “/” 示例

    @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 重定向示例

    原url有参数时,跳转是也得传参,注意:不用加类型

    #/old
    @app.route('/old/<int:nid>',redirect_to="/new/<nid>")
    def old(nid):
        return "old"
    # /new
    @app.route('/new/<int:nid>')
    def new(nid):
        return "new"

    subdomain 子域名示例

    from flask import Flask, views, url_for
    
    app = Flask(import_name=__name__)
    app.config['SERVER_NAME'] = 'haiyan.com:5000'
    
    
    @app.route("/", subdomain="admin")
    def static_index():
        return "admin.xxx.com"
    
    #动态生成 @app.route("/dynamic", subdomain="<username>") def username_index(username): return username + ".your-domain.tld" if __name__ == '__main__': app.run()

    路由系统的本质

    通过源码分析。
    @app.route()的本质就是执行了 add_url_rule(rule,endpoint,f,**options) 方法
    因此我们也可以在这里操作也可以添加路由映射 主流并不是用这种。就装饰器就可以了

    from flask import Flask
    
    app = Flask(__name__)
    app.config.from_object("settings.DevelopmentConfig")
    
    '''
    看到路由系统,分析路由系统干了什么?
    第一步:先执行:decorator = app.route("/", methods= ['GET','POST'], endpoint='n1')
        根据源码,第一步执行了下面的函数,返回decorator,这就是一个闭包,闭包给谁用,谁以后执行这个函数就给谁用
        def route(self, rule, **options):
            # 具体值与参数的对应关系:
            # app对象
            # rule = "/"
            # options = {methods= ['GET','POST'], endpoint='n1'}
            def decorator(f):
                endpoint = options.pop('endpoint', None)
                self.add_url_rule(rule, endpoint, f, **options)
                return f
            return decorator
    第二步: 第一步返回了decorator,所以相当于是: @decorator,等价于decorator(index),触发上面route函数下面的decorator函数的运行
            def decorator(f):
                endpoint = options.pop('endpoint', None)
                self.add_url_rule(rule, endpoint, f, **options)  # self就是app对象。加到了路由的对应表里去了,那里有url对应的函数
                return f
                
    最后总结一下,添加路由关系的本质,其实就是最终执行 self.add_url_rule(rule, endpoint, f, **options),生成路由的对应关系 
    
    '''
    #  对于endpoint还要注意:
    #  如果endpoint没有写,根据源码可知,默认的就是函数名,即该路由对应函数,如index(endpoint = index)
    @app.route("/", methods= ['GET','POST'], endpoint='n1')
    def index():
        return "Hello World!"
    
    def login():
        return "登录"
    
    # 所以根据源码的原理,也可以按照下面的方式添加路由对应关系,就与Django类似了。但是在Flask里,还是要按照装饰器的方式去添加路由对应关系
    app.add_url_rule('/login', 'n2', login, methods= ['GET','POST'])
    
    if __name__ == "__main__":
        app.run()

    CBV 的路由添加方式

    def auth(func):
        def inner(*args, **kwargs):
            result = func(*args, **kwargs)
            return result
        return inner
    
    
    class IndexView(views.MethodView):
        # methods = ['POST']  #只允许POST请求访问
        decorators = [auth,]  #如果想给所有的get,post请求加装饰器,就可以这样来写,也可以单个指定
    
        def get(self):   #如果是get请求需要执行的代码
            v = url_for('index')
            print(v)
            return "GET"
    
        def post(self):  #如果是post请求执行的代码
            return "POST"
    
    app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  #name指定的是别名,会当做endpoint使用
  • 相关阅读:
    手把手教你封装属于自己的分段滚动视图(上)
    从 setNeedsLayout 说起
    cocoapods使用指南
    神奇的 BlocksKit(1):源码分析(下)
    Web应用开发中的几个问题
    Jquery Ajax自定义无刷新提交表单Form
    解耦HTML、CSS和JavaScript
    通过预加载器提升网页加载速度
    巧妙使用CSS创建可以打印的页面
    有用的JavaScript开发小建议
  • 原文地址:https://www.cnblogs.com/shijieli/p/10354397.html
走看看 - 开发者的网上家园