域名设置:
说明: SERVER_NAME内置属性的设置会影响全局URL,它主要有两个作用,第一个作用是在请求上下文之外生成绝对URL,当然如果设置也会影响请求上下文内的绝对URL,第二个作用是用于子域名的支持
#!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # 51CTOBG: http://xmdevops.blog.51cto.com/ # Purpose: # """ # 说明: 导入公共模块 from flask import Flask, url_for # 说明: 导入其它模块 app = Flask(__name__) # app.url_map.default_subdomain='www' # app.config.update(SERVER_NAME='blog.51cto.com') with app.test_request_context(): print 'found notice: with request context full url is: %s' % ( url_for('static', filename='css/style.css', _external=True), ) with app.app_context(): print 'found notice: with app context full url is: %s' % ( url_for('static', filename='css/style.css', _external=True), ) if __name__ == '__main__': app.run(host='0.0.0.0', port=9000, debug=True)
说明: 如上代码在没有设置SERVER_NAME默认属性时,直接运行会报RuntimeError: Application was not able to create a URL adapter for request independent URL generation. You might be able to fix this by setting the SERVER_NAME config variable.说明url_for是依赖请求上下文的,若要生成不依赖于请求上下文(也就是说在请求上下文或程序上下文),最常见的就是异步发送邮件时url_for生成的邮件中的地址时就必须设置SERVER_NAME
子域实现:
说明: SERVER_NAME还用于子域名,因为FLASK在得知现有服务器名之前不能猜测出子域名部分,在请求上下文中如果没有设置SERVER_NAME,默认使用request.host,但是一旦设置SERVER_NAME,将全局影响全URL的主机部分,所以为了让FLASK以.分割识别子域名,强烈建议设置SERVER_NAME为指定域名,且指定名称的时候一定是SERVER_NAME='blog.51cto.com:9000'主域名加端口的形式,不然不会生效,如下就简单演示下常规项目开发中子域名的使用以及隔离资源文件及模版的方法,由于代码量有点多,就直接上传代码讲解
下载地址: http://1000eb.com/1kw8v
. │ main.py │ ├─app │ │ prod_config.py │ │ test_config.py │ │ __init__.py │ │ │ ├─monitor │ │ │ api.py │ │ │ views.py │ │ │ __init__.py │ │ │ │ │ ├─static │ │ │ └─js │ │ │ main.js │ │ │ │ │ └─templates │ ├─static │ └─templates ├─bin └─doc
1. main.py为入口文件,调用app包下的create_app函数创建app实例,然后调用app.run来启动实例
2. prod_config.py中为生产环境配置,再本地测试环境尝试导入test_config.py为当前配置,SERVER_NAME就在test_config.py中声明的,发布生产环境时删掉test_config.py即可
3. monitor包中定义了monitor蓝图,创建蓝图时指定subdomain='monitor',使得我们访问monitor.blog.51cto.com时会自动访问monitor蓝图,但是需要注意的是视图函数或是模版中使用url_for()生成路径时强烈推荐加上蓝图名,如上url_for('.static', filename='js/main.js', _external=True)/url_for('monitor.static', filename='js/main.js', _external=True)生成的是http://monitor.blog.51cto.com/static/js/main.js,对应的文件是app/monitor/static/js/main.js文件,而url_for('static', filename='js/main.js', _external=True)则生成的是https://blog.51cto.com/static/js/main.js,试图访问必然无法访问,一般遇到这种问题,可以用NGINX前端REWRITE重写下URL加一个默认子域名,如www即可解决
4. create_app函数主要加载prod_config.py中的配置,以及注册monitor包中的monitor蓝图
通配子域:
说明: 有时需要一个蓝图匹配多个子域名,比如51CTO给每个注册用户分配一个性域名类似http://xmdevops.blog.51cto.com/,且每个用户有自己的主页,以及不同的信息展示页面,此时就可以用动态URL
#!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # OsChina: http://xmdevops.blog.51cto.com/ # Purpose: # """ # 说明: 导入公共模块 from flask import Blueprint, g # 说明: 导入其它模块 monitor = Blueprint('monitor', __name__, subdomain='', static_folder='static', template_folder='templates') @monitor.url_value_preprocessor def set_site(endpoint, values): g.subdomain = values.pop('subdomain', None) @monitor.url_defaults def get_site(endpoint, values): values.update('subdomain', g.subdomain) @monitor.before_request def get_user(): # g.user = WebUser.query.filter_by(name=g.subdomain).first_or_404() g.user = g.subdomain if g.subdomain else None from . import api from . import views
说明: 在之前的代码上仅此修改了app/monitor/__init__.py中的代码,在创建蓝图时候修改参数subdomain='
扩展: 其实FLASK除了支持动态子域名其实还支持动态前缀,如果要实现https://blog.51cto.com:9000/home/