Refactored everything into a factory function

I now call a factory function to construct the Sanic app:

    app = app_factory(files)

This allows me to pass additional arguments to it, e.g. the files to serve.

Also refactored my class-based views to accept jinja as an argument, e.g:

    app.add_route(
        TableView.as_view(jinja),
        '/<db_name:[^/]+>/<table:[^/]+?><as_json:(.jsono?)?$>'
    )
This commit is contained in:
Simon Willison 2017-11-04 19:13:44 -07:00
commit 1fc75809a6
2 changed files with 61 additions and 41 deletions

View file

@ -25,15 +25,6 @@ SQL_TIME_LIMIT_MS = 1000
conns = {}
app = Sanic(__name__)
jinja = SanicJinja2(
app,
loader=FileSystemLoader([
str(app_root / 'datasite' / 'templates')
])
)
def get_conn(name):
if name not in conns:
info = ensure_build_metadata()[name]
@ -89,6 +80,9 @@ def ensure_build_metadata(regenerate=False):
class BaseView(HTTPMethodView):
template = None
def __init__(self, jinja):
self.jinja = jinja
def redirect(self, request, path):
if request.query_string:
path = '{}?{}'.format(
@ -147,7 +141,7 @@ class BaseView(HTTPMethodView):
if callable(extra_template_data)
else extra_template_data
)}
r = jinja.render(
r = self.jinja.render(
self.template,
request,
**context,
@ -159,32 +153,34 @@ class BaseView(HTTPMethodView):
return r
@app.route('/')
async def index(request, sql=None):
databases = []
for key, info in ensure_build_metadata().items():
database = {
'name': key,
'hash': info['hash'],
'path': '{}-{}'.format(key, info['hash'][:7]),
'tables_truncated': sorted(
info['tables'].items(),
key=lambda p: p[1],
reverse=True
)[:5],
'tables_count': len(info['tables'].items()),
'tables_more': len(info['tables'].items()) > 5,
'total_rows': sum(info['tables'].values()),
}
databases.append(database)
return jinja.render(
'index.html',
request,
databases=databases,
)
class IndexView(HTTPMethodView):
def __init__(self, jinja):
self.jinja = jinja
async def get(self, request):
databases = []
for key, info in ensure_build_metadata().items():
database = {
'name': key,
'hash': info['hash'],
'path': '{}-{}'.format(key, info['hash'][:7]),
'tables_truncated': sorted(
info['tables'].items(),
key=lambda p: p[1],
reverse=True
)[:5],
'tables_count': len(info['tables'].items()),
'tables_more': len(info['tables'].items()) > 5,
'total_rows': sum(info['tables'].values()),
}
databases.append(database)
return self.jinja.render(
'index.html',
request,
databases=databases,
)
@app.route('/favicon.ico')
async def favicon(request):
return response.text('')
@ -286,12 +282,6 @@ class RowView(BaseView):
}
app.add_route(DatabaseView.as_view(), '/<db_name:[^/\.]+?><as_json:(.jsono?)?$>')
app.add_route(DatabaseDownload.as_view(), '/<db_name:[^/]+?><as_db:(\.db)$>')
app.add_route(TableView.as_view(), '/<db_name:[^/]+>/<table:[^/]+?><as_json:(.jsono?)?$>')
app.add_route(RowView.as_view(), '/<db_name:[^/]+>/<table:[^/]+?>/<pk_path:[^/]+?><as_json:(.jsono?)?$>')
def resolve_db_name(db_name, **kwargs):
databases = ensure_build_metadata()
hash = None
@ -418,3 +408,32 @@ def sqlite_timelimit(conn, ms):
conn.set_progress_handler(handler, 10000)
yield
conn.set_progress_handler(None, 10000)
def app_factory(files):
app = Sanic(__name__)
jinja = SanicJinja2(
app,
loader=FileSystemLoader([
str(app_root / 'datasite' / 'templates')
])
)
app.add_route(IndexView.as_view(jinja), '/')
app.add_route(favicon, '/favicon.ico')
app.add_route(
DatabaseView.as_view(jinja),
'/<db_name:[^/\.]+?><as_json:(.jsono?)?$>'
)
app.add_route(
DatabaseDownload.as_view(jinja),
'/<db_name:[^/]+?><as_db:(\.db)$>'
)
app.add_route(
TableView.as_view(jinja),
'/<db_name:[^/]+>/<table:[^/]+?><as_json:(.jsono?)?$>'
)
app.add_route(
RowView.as_view(jinja),
'/<db_name:[^/]+>/<table:[^/]+?>/<pk_path:[^/]+?><as_json:(.jsono?)?$>'
)
return app

View file

@ -1,6 +1,6 @@
import click
from click_default_group import DefaultGroup
from .app import app, ensure_build_metadata
from .app import app_factory, ensure_build_metadata
@click.group(cls=DefaultGroup, default='serve', default_if_no_args=True)
@ -23,4 +23,5 @@ def build():
def serve(files, host, port, debug):
"""Serve up specified database files with a web UI"""
click.echo('Serve! files={} on port {}'.format(files, port))
app = app_factory(files)
app.run(host=host, port=port, debug=debug)