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.
An example would be:
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
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.
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.
Here's a little library I made a few years ago which might be helpful: https://github.com/wiota/landlord (this pattern is often called "multi-tenancy" or a "multi-tenant app", hence the name).
This is useful when you want to respond with essentially the same application with different content depending on the hostname, which seems to be what you're looking for.
In a nutshell, you wrap your existing app like this in your
app.py
:Then in your sub-application's
__init__.py
, thecreate_app
function gets ahostname
parameter, which allows you do do per-host logic: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.
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 settingstatic_host
so thestatic
route knows which host to to serve from. Unlike subdomains, you do not setSERVER_NAME
. Then pass thehost
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.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).
This example shows routing to any host of the form
{tree}tree.com
andadmin.{tree}tree.com
, withpinetree.com
as the static host.Blueprint
does not accept ahost
option yet, so you'll need to specify the host for each route. You can simplify this a bit usingpartial
.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 intog
instead of writing it as an argument for each view.During development, add the hosts your hosts file (
/etc/hosts
on Unix so they route to localhost.And run with: