""" views.py - defines the logic that generates views that a user sees when browsing to certain pages """ import os from flask import request, send_from_directory, abort from flask import render_template, render_template_string, make_response from siteconfig import siteconfig from server import app, cache from view_functions import default_context, index_dir, is_hidden_path # bit of a hack. # Brackets don't play nicely with Jinja so instead of using .format, # we just replace the special character $ CONTENT_BLOCK = ( "{% extends 'base.html' %}{% block content %}${% endblock %}" ) @app.route("/") @app.route("/site") @app.route("/site/home.html") @app.route("/site/index.html") @cache.cached() def home(): """ home - renders the template `home.html` as the main index file If you'd like to customize your home page, that is the file you want to edit, though you can optionally change the title here if you wish """ context = default_context() context.update( {'title': app.config['HOME_TITLE'], 'parent_dir': '/site/'} ) return render_template("site/home.html", **context) # from: https://pythonise.com/series/learning-flask/sending-files-with-flask @app.route("/site/") @cache.cached() def render_file(path): """ render_file - renders an HTML document for the given `path`. If `path` is an HTML file it is rendered within the base template, otherwise, the raw file is returned. If `path` points to a directory, this function instead creates an index for the directory containing it's files, links, and other info. """ if is_hidden_path(path): abort(404) abs_path = siteconfig.BASE_DIR + path context = default_context() context.update( { 'title': path.split('.')[0].upper(), 'parent_dir': '/site/' + '/'.join(path.split('/')[:-1]), } ) if os.path.isfile(abs_path): if abs_path.endswith('.html'): with open(abs_path, 'rb') as f: content = f.read().decode("UTF-8") return render_template_string( CONTENT_BLOCK.replace('$', content), **context ) elif abs_path.endswith('.html!'): return render_template("site/" + path, **context) else: # not an html file, so don't render it return send_from_directory( siteconfig.BASE_DIR, path, mimetype=siteconfig.MIMETYPES.get( f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE, ), ) elif os.path.isdir(abs_path): dirs, files, links, description = index_dir(abs_path) context.update( { 'cur_path': 'site/' + path, 'cur_dir': path.split('/')[-1] + '/', 'dirs': dirs, 'files': files, 'links': links, 'description': description, } ) return render_template("index.html", **context) else: context.update({'errors': "404 File not found"}) return render_template("base.html", **context) @app.route("/raw/") @cache.cached() def send_file_from_site(path): """ send_file_from_site - instead of rendering a file within a template as with `render_file`, send the raw file to the user """ return send_from_directory( siteconfig.BASE_DIR, path, mimetype=siteconfig.MIMETYPES.get( f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE ), ) @app.route("/static/") @cache.cached() def send_file_from_static(path): """ send_file_from_static - send files from the static directory """ return send_from_directory( 'static/', path, mimetype=siteconfig.MIMETYPES.get( f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE ), ) @app.route("/feed.xml") @cache.cached() def render_rss_feed(): context = { 'config': siteconfig.rss_channel_config, 'items': app.config['RSS_CHANNEL'], } feed = render_template("feed.xml", **context) response = make_response(feed) response.headers['Content-Type'] = siteconfig.MIMETYPES.get(".xml") return response