Flask应用程序,可路由到多个顶级域和子域 [英] Flask app that routes to multiple top level and sub domains

查看:52
本文介绍了Flask应用程序,可路由到多个顶级域和子域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,它需要多个域指向同一应用程序并显示不同的数据,但是我在所有域中也有相同的"admin"子域,根据域的不同,该子域还显示不同的数据.

I have an app that requires multiple domains pointing to the same app with different data being displayed, but I also have the same "admin" subdomain across all domains which also displays different data depending on the domain.

一个例子是:

pinetree.com - displays information about pine trees
oaktree.com - displays information about oak trees

admin.pinetree.com - displays admin for managing pine trees
admin.oaktree.com - displays admin for managing oak trees

到目前为止,我发现您需要在Flask配置中编写 SERVER_NAME (域名),以便将子域与Flask一起使用,但是由于我有许多不同类型的树唯一的域,并且一直在添加新的树,我看不到如何使用该功能.

So far, I've found that you need to write the SERVER_NAME (domain name) in the Flask config in order to use subdomains with Flask, but since I have many different types of trees with unique domains, and new trees are added all the time, I don't see how I could use that functionality.

此外,我已经看到GAE flexible没有多租户,这是我最初想到的将是在GAE上管理多个域的方式.

Also, I have seen that GAE flexible doesn't have multitenancy, which is what I had first thought would be the way to manage multiple domains on GAE.

推荐答案

子域如果您的一个基础域包含多个子域,则应使用另一答案中解释的匹配方式.因为Flask可以推断出与其匹配的URL有关的更多信息,所以更为简单.

Subdomain matching, explained in another answer, should be used if you have one base domain with several subdomains. It's more straightforward since Flask can infer more about the URLs it's matching.

但是,如果您有多个基本域,则应使用主机匹配代替.您必须在应用程序对象上设置 host_matching = True ,并设置 static_host ,以便 static 路由知道要从哪个主机提供服务.与子域不同,您无需设置 SERVER_NAME .然后将 host 选项传递给路由.这与完整域匹配,因此每次都需要写出完整域,而不仅仅是子域.

However, if you have multiple base domains, you should use host matching instead. You must set host_matching=True on the app object, as well as setting static_host so the static route knows which host to to serve from. Unlike subdomains, you do not set SERVER_NAME. Then pass the host option to routes. This matches against the full domain, and so it requires writing out the full domain each time, rather than just the subdomain.

不幸的是,匹配完整主机意味着也要匹配端口.在开发服务器下,默认情况下该端口为5000,但在生产中该端口可能为80、443或其他.您可以编写一个小助手,以在开发模式(或部署所需的任何配置逻辑)中运行时将端口设置为5000.

Unfortunately, matching the full host means matching the port as well. Under the dev server, the port will be 5000 by default, but in production the port may be 80, 443, or something else. You can write a small helper to set the port to 5000 when running in development mode (or whatever configuration logic you need for your deployment).

from flask.helpers import get_env

def p(host):
    if get_env() == "development":
        return host + ":5000"

    return host

# p("example.com") -> "example.com:5000"

此示例显示使用 pinetree.com路由到任何形式为 {tree} tree.com admin.{tree} tree.com 的主机作为静态主机.

This example shows routing to any host of the form {tree}tree.com and admin.{tree}tree.com, with pinetree.com as the static host.

from flask import Flask
app = Flask(__name__, host_matching=True, static_host=p("pinetree.com"))

@app.route("/", host=p("<tree>tree.com"))
def index(tree):
    return f"{tree} tree"

蓝图尚不接受 host 选项,因此您需要为每个路由指定主机.您可以使用 partial 对此进行一些简化.

Blueprint does not accept a host option yet, so you'll need to specify the host for each route. You can simplify this a bit using partial.

from functools import partial
from flask import Blueprint

admin = Blueprint("admin", __name__)
admin_route = partial(admin.route, host=p("admin.<tree>tree.com"))

@admin_route("/")
def index(tree):
    return f"admin for {tree} tree"

app.register_blueprint(admin)

请注意,主机可以采用URL参数,就像路由中的路径一样.它将像路径参数一样传递给视图.这允许动态主机和子域.您可以使用 @ app.url_defaults @ app.url_value_preprocessor 进行提取将其写入 g 中,而不是将其作为每个视图的参数写入.

Note that the host can take URL parameters just like the path in the route. It will be passed to views just like path parameters. This allows for dynamic hosts and subdomains. You can use @app.url_defaults and @app.url_value_preprocessor to extract this into g instead of writing it as an argument for each view.

from flask import g

@app.url_value_preprocessor
def extract_tree(endpoint, values):
    g.tree = values.pop("tree")

@app.url_defaults
def inject_tree(endpoint, values):
    values.setdefault("tree", g.tree)

@app.route("/")
def index()
    return f"{g.tree} tree"

在开发过程中,将主机添加到您的主机文件(在Unix上为/etc/hosts ,以便它们路由到本地主机.

During development, add the hosts your hosts file (/etc/hosts on Unix so they route to localhost.

127.0.0.1 localhost pinetree.com admin.pinetree.com oaktree.com admin.oaktree.com

并运行:

export FLASK_ENV=development
flask run

这篇关于Flask应用程序,可路由到多个顶级域和子域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆