aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README16
-rw-r--r--server.py184
-rw-r--r--templates/base.html4
-rw-r--r--templates/site/tutorials/py-style.html0
-rw-r--r--views.py180
5 files changed, 204 insertions, 180 deletions
diff --git a/README b/README
index ddc1932..a0a84f2 100644
--- a/README
+++ b/README
@@ -24,11 +24,11 @@ elsewhere.
Why not just use a database or the million other CMS software packages out
there? Zero reason not to! I just wanted to see what it would look like to
build something from the ground up WITHOUT having to copy HTML over and over
-again. Databases are great, but so are filesystems, and I see no reason to
+again. Databases are great, but so are file systems, and I see no reason to
overcomplicate when making a simple home page. This software is primarily
geared towards bloggers or people who want a home page like it's 1999, but
Flask has great documentation so I think you'll find it a pleasure to build on
-top of.
+top of if you want to get creative.
### Why not just neocities?
@@ -58,8 +58,10 @@ $ python server.py
```
Your server will (by default) be hosted on http://127.0.0.1:5000
-and have the `templates/site/` directory mounted. You should see `home.html`
-render.
+and have the `templates/site/` directory delivered to your users when they
+access http://127.0.0.1:5000/site/
+
+You should see `home.html` render on the root directory.
## Adding Pages
@@ -70,7 +72,7 @@ particular is special since it contains the top-level folders which will be
used to navigate your site, but any folders beneath will be automatically
indexed.
-As an excercise, add a file to the `templates/site/thoughts/rants` folder
+As an exercise, add a file to the `templates/site/thoughts/rants` folder
called `myrant.html` and put the following content:
`<p>I don't like spam!</p>`
@@ -185,7 +187,7 @@ replace the HTML with your own license (or none), by editing
`templates/site/license.html`
-### Other tips
+### Other Tips
There are a few special directories linked that are needed to
customize your site. First the `static` directory, which holds your static
@@ -204,6 +206,8 @@ documented. A quickstart looks like this:
```bash
$ sudo pip install uwsgi
+$ sudo mkdir /var/path/to/your-flask/
+$ sudo chown www-data -R /var/path/to/your-flask
$ uwsgi -s /var/path/to/your-flask.sock --manage-script-name --mount /=server:app --virtualenv ./env
```
diff --git a/server.py b/server.py
index e2e93f0..e77485c 100644
--- a/server.py
+++ b/server.py
@@ -1,183 +1,15 @@
import os
from flask import Flask
-from flask import request, send_from_directory, abort
-from flask import render_template, render_template_string
from siteconfig import siteconfig
app = Flask(__name__)
-# bit of a hack.
-# Brackets don't play nicely with Jinja so instead of using .format,
-# we just replace the special charcater $
-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.
-
- 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
- """
- dirs = []
- files = []
- links = []
- description = ""
- 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:
- with open(path + '/' + obj) as f:
- description = f.read()
- 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, diretories won't actually be "hidden" but
- they are still not indexed by this program
- """
- return path.split('/')[-1].startswith('.')
-
-
-@app.route("/")
-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': '/'
- }
- )
- return render_template("site/home.html", **context)
-
-
-# from: https://pythonise.com/series/learning-flask/sending-files-with-flask
-@app.route("/<path:path>")
-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 = "./templates/site/" + path
- context = default_context()
- context.update(
- {
- 'title': path.split('.')[0].upper(),
- 'parent_dir': '/' + '/'.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('templates/site/', 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_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/<path:path>")
-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
- """
- return send_from_directory('template/site/', path,
- mimetype=siteconfig.MIMETYPES.get(
- f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE
- )
- )
-
-
-@app.route("/static/<path:path>")
-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
- """
- return send_from_directory('static/', path,
- mimetype=siteconfig.MIMETYPES.get(
- f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE
- )
- )
-
+from views import *
def setup():
"""
setup - sets up the app according to the settings specified (or not
- speified) in `siteconfig`
+ specified) in `siteconfig`
"""
if siteconfig.SECRET_KEY:
app.config['SECRET_KEY'] = siteconfig.SECRET_KEY
@@ -188,12 +20,20 @@ def setup():
if siteconfig.MAIN_SITE_DIRS:
app.config.update({'MAIN_SITE_DIRS': siteconfig.MAIN_SITE_DIRS})
else:
- app.config.update({'MAIN_SITE_DIRS': index_dir('./templates/site')[0]})
+ s = './templates/site/'
+ top_dirs = [
+ x for x in os.listdir(s) if os.path.isdir(s + x)
+ ]
+ app.config.update(
+ {
+ 'MAIN_SITE_DIRS': sorted(top_dirs)
+ }
+ )
app.config.update({'DOMAIN': siteconfig.DOMAIN})
app.config.update({'HOME_TITLE': siteconfig.HOME_TITLE})
-# Need to come first to be compatible with wsgi
+# Setup needs to come first to be compatible with wsgi
setup()
if __name__ == '__main__':
app.run()
diff --git a/templates/base.html b/templates/base.html
index 5c4e189..6476091 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -13,7 +13,7 @@
<div class="navbar">
<b>|</b> <!-- This makes the bar symmetrical -->
{% for dir in navbar %}
- <b> <a href="/{{ dir }}">{{ dir }}/</a> |</b>
+ <b> <a href="/site/{{ dir }}">{{ dir }}/</a> |</b>
{% endfor %}
</div>
<h2>{{ title }}</h2>
@@ -21,7 +21,7 @@
{% block content %}
{% endblock %}
<h3>{{ errors }}</h3>
- {% if parent_dir != '/' %}
+ {% if parent_dir != '/site/' %}
<h3><a href="{{ parent_dir }}">Go up to parent folder ({{ parent_dir }})</a></h3>
{% endif %}
</div>
diff --git a/templates/site/tutorials/py-style.html b/templates/site/tutorials/py-style.html
deleted file mode 100644
index e69de29..0000000
--- a/templates/site/tutorials/py-style.html
+++ /dev/null
diff --git a/views.py b/views.py
new file mode 100644
index 0000000..c4e3fe2
--- /dev/null
+++ b/views.py
@@ -0,0 +1,180 @@
+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
+
+# 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 free text. Both are displayed on the index.html
+ for the given `path`
+ """
+ dirs = []
+ files = []
+ links = []
+ description = ""
+ 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:
+ with open(path + '/' + obj) as f:
+ description = f.read()
+ 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('.')
+
+
+@app.route("/")
+@app.route("/site")
+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/<path:path>")
+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 = "./templates/site/" + 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(
+ 'templates/site/',
+ 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_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/<path:path>")
+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.
+ """
+ return send_from_directory('templates/site/', path,
+ mimetype=siteconfig.MIMETYPES.get(
+ f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE
+ )
+ )
+
+
+@app.route("/static/<path:path>")
+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
+ """
+ return send_from_directory('static/', path,
+ mimetype=siteconfig.MIMETYPES.get(
+ f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE
+ )
+ )