在之前的文章中,我们讲到Flask中的SERVER_NAME
主要做两件事:
- 协助Flask生成请求上下文之外的URL(比如邮件)
- 用于子域名支持
今天我们就来讲讲子域名这部分。
Flask子域名
一般用于数量比较少的子域名,一个模块对应一个子域名。先看下面一个例子:
modules.py
:
from flask import Blueprint
public = Blueprint('public', __name__)
@public.route('/')
def home():
return 'hello flask'
app.py
:
app = Flask(__name__)
app.config['SERVER_NAME'] = 'example.com'
from modules import public
app.register_blueprint(public, subdomain='public')
现在可以通过public.example.com/
来访问public
模块了。
通配符子域
通配符子域,即通过一个模块来匹配很多个子域名。比如某些网站提供的个性化域名功能,就是这种形式。
先来看段示例代码:
modules.py
:
from flask import Blueprint
member = Blueprint('member', __name__)
@member.route('/')
def home():
return g.subdomain
app.py
:
app = Flask(__name__)
app.config['SERVER_NAME'] = 'example.com'
from modules import member
app.register_blueprint(member, subdomain='<subdomain>')
这段代码和上一节的第像,不同之处是这里的subdomain
使用了动态参数<subdomain>
(路由中的URL变量也是这种方式)。我们可以用这个参数在请求回调函数之前利用的组合的url处理器来获取相关的用户。这样我们就可以通过*.example.com
的形式来访问member
模块了。
下面是为任何Flask
或Blueprint
对象增加子域名支持的便捷函数:
def add_subdomain_to_global(endpoint, values):
g.subdomain = values.pop('subdomain', None)
def add_subdomain_to_url_params(endpoint, values):
if not 'subdomain' in values:
values['subdomain'] = g.subdomain
def add_subdomain_support(app):
app.url_value_preprocessor(add_subdomain_to_global)
app.url_defaults(add_subdomain_to_url_params)
然后你可以使用before_request
回调函数来处理子域名:
add_subdomain_support(blueprint)
@blueprint.before_request
def add_user_to_global():
g.user = None
if g.subdomain:
g.user = User.query.filter_by(username=g.subdomain).first_or_404()
注:这里的blueprint
请改为实际对象。
特别说明:通配符子域调试不是不太方便,需要做泛域名解析才可以。修改hosts文件来指定域名的方法是不可行的(子域名较少时可以逐个添加,子域名多了就不太现实了)。本机调试时,可以安装DNS服务器(比如LINUX BIND服务等),并做好泛域名解析,然后再进行调试。当然使用公网域名和服务器来调试也未尝不可。
英文好的同学可以参阅:Getting bigger with Flask