配置文件系统
自定义配置文件
创建一个 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,
路由系统
FBV 的路由添加方式
语法
@App.route(参数)
参数
- @App.route("/index/<int:nid>",methods=["POST","GET"],endpoint="n1") # 自己定义的装饰器要放在路由装饰器下面
- """
- rule
- /index/<int:nid> 动态路由, 路径中可以带参数 , 必须要指定类型
- 仅允许的类型 :
- 默认不指定的时候按 str 处理
- string 字符串
- float 浮点型
- path 路径
- int 整型
- any 任何
- uuid uuid 类型
- 默认的不支持正则路由匹配的
- methods=["GET","POST"]
- 规定只允许的请求方式
- default={"k":"v"}
- URL 中无参数, 函数又需要参数时, 添加默认值
- endpoint="n1"
- 类似于 django 中的反向解析用的 name="" 未指定的时候默认是绑定函数名 endpoint="index"
- ps:
- 如果两个函数都用了装饰器, 装饰器还没有 wraps
- endpoint 默认等于 函数名.
- 会把装饰器内的 inner 作为 endpoint 值导致出问题
- 因此如果再加装装饰器一定要加 wraps
- view_func
- 视图函数名称
- strict_slashes="True"
- 对最后的 url 的 "/" 是否严格要求
- 默认是严格匹配
- redirect_to="/index/<nid>"
- 重定向, 可加参数, 原 url 有参数时, 跳转是也得传参
- subdomain=None
- 子域名访问
- 注意事项:
- endpoint 不能重名
- 源码将 endpoint 和函数名一起进行的判断.
- 如果一定要重名, 拿函数要相同, 不然会报错
- 总之不要重名就行了
- """
- def index(nid): # 接受 url 中参数
- print(url_for(n1)) # 返回路径
- print(url_for("n1",nid=999)) # 返回带参数的路径
- return "index"
URL 示例
- @App.route('/user/<username>') #常用的 不加参数的时候默认是字符串形式的
- @App.route('/post/<int:post_id>') #常用的 #指定 int, 说明是整型的
- @App.route('/post/<float:post_id>')
- @App.route('/post/<path:path>')
- @App.route('/login', methods=['GET', 'POST'])
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 使用
来源: http://www.bubuko.com/infodetail-2946430.html