diff options
author | mjfernez <mjfernez@gmail.com> | 2021-10-10 22:15:07 -0400 |
---|---|---|
committer | mjfernez <mjfernez@gmail.com> | 2021-10-10 22:15:07 -0400 |
commit | 02a37ad308fbcc27a04787c84a76de7c2936a6d5 (patch) | |
tree | df25089ab76cc0c3faa94e2990b600ea7568ab63 | |
parent | a800163aeae0998fa49f011664f32a6c348db886 (diff) | |
download | ezcms-02a37ad308fbcc27a04787c84a76de7c2936a6d5.tar.gz |
Caching support. Separate views.py in 2 files
This commit adds the Flask-Caching module to the software stack and
enables the caching of views in a wide variety of ways, but implemented
here to be simple to understand to someone new to the concept of caching
(aka me).
Various documentation and formatting was applied to all files. views.py
internal functions (mostly related to filesystem operations of the
server). have been moved into view_functions.py
-rw-r--r-- | requirements.txt | 1 | ||||
-rw-r--r-- | server.py | 21 | ||||
-rw-r--r-- | siteconfig.py | 32 | ||||
-rw-r--r-- | view_functions.py | 71 | ||||
-rw-r--r-- | views.py | 94 |
5 files changed, 134 insertions, 85 deletions
diff --git a/requirements.txt b/requirements.txt index 63d0835..b3c4209 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,3 +7,4 @@ pip==20.3.4 setuptools==44.1.1 Werkzeug==2.0.1 Flask-Compress==1.10.1 +Flask-Caching==1.10.1 @@ -1,10 +1,20 @@ +""" +server.py - sets up and runs the flask server +""" import os from flask import Flask from siteconfig import siteconfig from flask_compress import Compress +from flask_caching import Cache app = Flask(__name__) compress = Compress() +cache = Cache( + config={ + 'CACHE_TYPE': siteconfig.CACHE_TYPE, + 'CACHE_DEFAULT_TIMEOUT': siteconfig.CACHE_DEFAULT_TIMEOUT, + } +) from views import * @@ -25,17 +35,22 @@ def setup(): else: s = "./templates/site/" top_dirs = [ - x for x in os.listdir(s) \ - if os.path.isdir(s + x) and not x.startswith(".") + x + for x in os.listdir(s) + if os.path.isdir(s + x) and not x.startswith(".") ] app.config.update({'MAIN_SITE_DIRS': sorted(top_dirs)}) app.config.update({'DOMAIN': siteconfig.DOMAIN}) app.config.update({'HOME_TITLE': siteconfig.HOME_TITLE}) - app.config.update({'COMPRESS_MIMETYPES': siteconfig.COMPRESS_MIMETYPES}) + app.config.update( + {'COMPRESS_MIMETYPES': siteconfig.COMPRESS_MIMETYPES} + ) + # Setup needs to come first to be compatible with wsgi setup() if __name__ == "__main__": compress.init_app(app) + cache.init_app(app) app.run() diff --git a/siteconfig.py b/siteconfig.py index fa73b46..4e0ef90 100644 --- a/siteconfig.py +++ b/siteconfig.py @@ -1,15 +1,20 @@ +""" +siteconfig.py - user editable configuration file +""" + + class siteconfig: # REQUIRED SETTINGS# - DOMAIN = "example.net" # Your site here! - HOME_TITLE = "WELCOME" # Goes right under - # your site - LINKS_FILE = ".links" # ".lnx" if you like - DESC_FILE = ".description" # ".desc" - DEFAULT_MIMETYPE = "application/octet-stream" + DOMAIN = "example.net" # Your site here! + HOME_TITLE = "WELCOME" # Goes right under + # your site + LINKS_FILE = ".links" # ".lnx" if you like + DESC_FILE = ".description" # ".desc" + DEFAULT_MIMETYPE = "application/octet-stream" # ^This usually prompts a browser to download a file if the mime # type is unknown. A good alternative might be "text/plain" - + # Add your desired mimetypes to the csv file MIMETYPES = {} with open('mimetypes.csv') as f: @@ -23,9 +28,18 @@ class siteconfig: # ./templates/site/. You can change this to only specific directories, but # these still have to be in ./templates/site MAIN_SITE_DIRS = None # ["dir1", "dir2", "dir3"] + # Set a custom secret key. If not set, it will be generated # Most of the time, you don't need to set this! - SECRET_KEY = None # Something random. - # Special option for Flask Compress + SECRET_KEY = None # Something random. + + # Option for Flask Compress # see here https://pypi.org/project/Flask-Compress/ COMPRESS_MIMETYPES = list(MIMETYPES.values()) + + # Option for Flask Caching + # https://flask-caching.readthedocs.io/en/latest/#configuring-flask-caching + CACHE_TYPE = "SimpleCache" + + # Time in seconds that your files stay cached for + CACHE_DEFAULT_TIMEOUT = 300 diff --git a/view_functions.py b/view_functions.py new file mode 100644 index 0000000..64dcfe0 --- /dev/null +++ b/view_functions.py @@ -0,0 +1,71 @@ +""" +view_functions.py - defines functions called by views to display the correct data +about files and paths. +""" +import os +from siteconfig import siteconfig +from server import app + + +def default_context(): + """ + default_context - returns the minimum info needed to render a template--the + domain name (for the home directory), and the top site directories which + make up the navbar + """ + return { + 'domain': app.config['DOMAIN'], + 'navbar': sorted(app.config['MAIN_SITE_DIRS']), + } + + +def index_dir(path): + """ + index_dir - Given a directory at `path`, list it's contents, + and sort each item as a file or a directory or a special file. + + return - a tuple with the values: + > a list of directories in `path`, + > a list of files in `path`, + > (if present), a list of external links to add to the index.html of the + directory + > (if present), a short description (string) of what the directory contains + + Lists are sorted alphabetically. + + *Special files include '.links' and '.description' the format of these + files is unquoted CSV and text/html. Both are displayed on the index.html + for the given `path` + """ + dirs = [] + files = [] + links = [] + description = False + contents = os.listdir(path) + for obj in contents: + if os.path.isfile(path + '/' + obj): + if obj == siteconfig.LINKS_FILE: + with open(path + '/' + obj) as f: + links = f.readlines() + elif obj == siteconfig.DESC_FILE: + description = True + elif obj.startswith('.'): + continue + else: + files.append(obj) + elif os.path.isdir(path + '/' + obj): + if obj.startswith('.'): + continue + else: + dirs.append(obj) + + return sorted(dirs), sorted(files), sorted(links), description + + +def is_hidden_path(path): + """ + Tests if last object specified in `path` is hidden. + Inspired by Unix. On Windows, directories won't actually be "hidden" but + they are still not indexed by this program + """ + return path.split('/')[-1].startswith('.') @@ -1,81 +1,25 @@ +""" +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 from siteconfig import siteconfig -from server import app +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 %}" - - -def default_context(): - """ - default_context - returns the minimum info needed to render a template--the - domain name (for the home directory), and the top site directories which - make up the navbar - """ - return { - 'domain': app.config['DOMAIN'], - 'navbar': sorted(app.config['MAIN_SITE_DIRS']), - } - - -def index_dir(path): - """ - index_dir - Given a directory at `path`, list it's contents, - and sort each item as a file or a directory or a special file. - - return - a tuple with the values: - > a list of directories in `path`, - > a list of files in `path`, - > (if present), a list of external links to add to the index.html of the - directory - > (if present), a short description (string) of what the directory contains - - Lists are sorted alphabetically. - - *Special files include '.links' and '.description' the format of these - files is unquoted CSV and text/html. Both are displayed on the index.html - for the given `path` - """ - dirs = [] - files = [] - links = [] - description = False - contents = os.listdir(path) - for obj in contents: - if os.path.isfile(path + '/' + obj): - if obj == siteconfig.LINKS_FILE: - with open(path + '/' + obj) as f: - links = f.readlines() - elif obj == siteconfig.DESC_FILE: - description = True - elif obj.startswith('.'): - continue - else: - files.append(obj) - elif os.path.isdir(path + '/' + obj): - if obj.startswith('.'): - continue - else: - dirs.append(obj) - - return sorted(dirs), sorted(files), sorted(links), description - - -def is_hidden_path(path): - """ - Tests if last object specified in `path` is hidden. - Inspired by Unix. On Windows, directories won't actually be "hidden" but - they are still not indexed by this program - """ - return path.split('/')[-1].startswith('.') +CONTENT_BLOCK = ( + "{% extends 'base.html' %}{% block content %}${% endblock %}" +) @app.route("/") @app.route("/site") +@cache.cached() def home(): """ home - renders the template `home.html` as the main index file @@ -84,12 +28,15 @@ def home(): 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/'}) + 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/<path:path>") +@cache.cached() def render_file(path): """ render_file - renders an HTML document for the given `path`. @@ -124,7 +71,8 @@ def render_file(path): 'templates/site/', path, mimetype=siteconfig.MIMETYPES.get( - f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE + f".{ path.split('.')[-1] }", + siteconfig.DEFAULT_MIMETYPE, ), ) elif os.path.isdir(abs_path): @@ -146,11 +94,11 @@ def render_file(path): @app.route("/raw/<path:path>") +@cache.cached() def send_file_from_site(path): """ - send_file - instead of rendering a file within a template as with - `render_file`, send the raw file to the user, when site is replace with - 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( 'templates/site/', @@ -162,10 +110,10 @@ def send_file_from_site(path): @app.route("/static/<path:path>") +@cache.cached() def send_file_from_static(path): """ - send_file - instead of rendering a file within a template as with - `render_file`, send the raw file to the user + send_file_from_static - send files from the static directory """ return send_from_directory( 'static/', |