Created
May 26, 2016 16:04
-
-
Save mrjoes/75dc5a1d65ce305406311e98abe1155b to your computer and use it in GitHub Desktop.
Flask-Admin with multiple virtual subdomains
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<body> | |
Hello {{ subdomain }}! | |
<img src="{{ url_for('static', subdomain=subdomain, filename='avatar.jpeg', _external=True) }}"></img> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from flask import Flask, render_template, g | |
from flask_admin import BaseView, AdminIndexView, Admin, expose | |
# Custom Flask app which allows us to send static files from different import | |
# subdomains | |
class DemoApp(Flask): | |
# Send static file and set CORS policy | |
def send_static_file(self, filename, subdomain=None): | |
response = super(DemoApp, self).send_static_file(filename) | |
response.headers['Access-Control-Allow-Origin'] = '*' | |
return response | |
# Admin mixin class | |
class AdminMixin(object): | |
# Subdomain helpers - store current subdomain in the Flask `g` object | |
@property | |
def subdomain(self): | |
return getattr(g, 'subdomain', None) | |
@subdomain.setter | |
def subdomain(self, value): | |
g.subdomain = value | |
# Overrides `get_url` - current `subdomain` will be always injected into `url_for` | |
def get_url(self, endpoint, **kwargs): | |
kwargs.setdefault('subdomain', self.subdomain) | |
return super(AdminMixin, self).get_url(endpoint, **kwargs) | |
# Removes `subdomain` arg before calling admin views, so we don't have to | |
# override each and every of them | |
def _run_view(self, fn, *args, **kwargs): | |
if 'subdomain' in kwargs: | |
self.subdomain = kwargs.pop('subdomain') | |
return fn(self, *args, **kwargs) | |
# This is our base admin view. Can do the same for ModelView | |
class AdminView(AdminMixin, BaseView): | |
pass | |
# This is custom administrative index view | |
class IndexView(AdminMixin, BaseView): | |
def __init__(self): | |
# Lets initialize as usual | |
super(IndexView, self).__init__(name='Home', | |
category=None, | |
url='/admin', | |
endpoint='admin', | |
static_folder=None) | |
# Our home page | |
@expose() | |
def index(self): | |
return self.render('admin/index.html') | |
# Custom `send_static_file` that knows how to handle subdomains | |
def send_static_file(self, filename, subdomain=None): | |
# There's a better way - just send file using `send_from_directory` | |
# instead of messing around with static_folder value. But for sake of | |
# example - it works. | |
if self.blueprint.static_folder is None: | |
self.blueprint.static_folder = 'static' | |
return self.blueprint.send_static_file(filename) | |
# Override blueprint creation logic and add static URL rule | |
def create_blueprint(self, admin): | |
bp = super(IndexView, self).create_blueprint(admin) | |
app.add_url_rule('/admin/static/<path:filename>', | |
endpoint='admin.static', | |
subdomain='<subdomain>', | |
view_func=self.send_static_file) | |
return bp | |
# Just a test admin view | |
class TestView(AdminView): | |
@expose() | |
def index(self): | |
return self.render('test.html', | |
subdomain=self.subdomain) | |
# Lets create Flask app and disable automatic static folder | |
app = DemoApp(__name__, static_folder=None) | |
# Demo view | |
@app.route('/', subdomain='<subdomain>') | |
def index(subdomain): | |
return render_template('demo.html', subdomain=subdomain) | |
def run(): | |
# Preconfigure the app | |
app.static_folder = 'static' | |
app.config['SERVER_NAME'] = 'demo.dev:5000' | |
# Add static URL rules | |
app.add_url_rule('/static/<path:filename>', | |
endpoint='static', | |
view_func=app.send_static_file) | |
app.add_url_rule('/static/<path:filename>', | |
endpoint='static', | |
subdomain='<subdomain>', | |
view_func=app.send_static_file) | |
# Create admin, use custom IndexView() that'll inject Flask-Admin static | |
# folders | |
admin = Admin(app, | |
subdomain='<subdomain>', | |
index_view=IndexView()) | |
admin.add_view(TestView()) | |
app.run(debug=True) | |
if __name__ == '__main__': | |
run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% extends 'admin/master.html' %} | |
{% block body %} | |
Hello for {{ subdomain }}! | |
{% endblock %} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment