-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.py
138 lines (98 loc) · 4.55 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import os
import glob
import re
from flask import Flask, request, Response, render_template, jsonify, redirect
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from flask_bootstrap import Bootstrap5
from werkzeug.utils import secure_filename
from jinja2 import Environment, FileSystemLoader, meta
# The directory containing the Jinja2 templates
TEMPLATE_FOLDER = "templates"
# Initialize the Flask application
app = Flask(__name__)
# Needed for CSRF protection, else WTForms will not run
app.config['SECRET_KEY'] = 'any secret string'
# Load Bootstrap files from local resources instead of CDN
app.config["BOOTSTRAP_SERVE_LOCAL"] = True
# Bootstrap the app using to Bootstrap-Flask
bootstrap = Bootstrap5(app)
@app.route("/", methods=["GET"])
def view_template_list():
'''
Homepage - Display a list of all the available templates with some quick help.
'''
# Get all the Jinja2 files inside the templates folder
template_list = glob.glob("*.j2", root_dir=TEMPLATE_FOLDER)
# Remove the file extension to keep only the name of the template
template_list = [ t.strip(".j2") for t in template_list ]
return render_template("home.html", items=template_list, template_folder=TEMPLATE_FOLDER)
@app.route("/templates/<template_name>", methods=["GET", "POST"])
def template_engine(template_name: str):
'''
Display or render templates
The template name and related Jinja2 file name are retrieved from the URL.
Template files shoud use the .j2 extension by default.
'''
# Build the template filename from the URL endpoint
template_file = template_name + ".j2"
# Use the GET method to retrieve the raw template as plain text
if request.method == "GET":
# Load the actual data from the .j2 file inside the template folder
with open(os.path.join(TEMPLATE_FOLDER, template_file)) as f:
data = f.read()
# Return the raw content of the template file as plain text
return Response(data, mimetype="text/plain")
# Use the POST method to render the template
elif request.method == "POST":
# If we receive the request as application/json we return JSON
if request.content_type == "application/json":
variables = request.get_json()
return jsonify(result=render_template(template_file, **variables))
# If we receive the request as application/x-www-for-urlencoded we return plain text
elif request.content_type == "application/x-www-form-urlencoded":
variables = request.form.to_dict()
return Response(response=render_template(template_file, **variables), mimetype="text/plain")
@app.route("/forms/<template_name>", methods=["GET"])
def form_generator(template_name: str):
'''
Automatically generate a Bootstrapped web form from a Jinja2 template
'''
# Define a new class with an input field for each variable in the template
class FormGenerator(FlaskForm):
# Build the template filename from the URL endpoint
template_file = template_name + ".j2"
# Get all variables in the Jinja2 template
with open(os.path.join(TEMPLATE_FOLDER, template_file)) as f:
data = f.read()
variables = re.findall("\{\{ (\S+) \}\}", data)
'''
# Get all variables in the Jinja2 template (hacky...)
env = Environment(loader=FileSystemLoader("./templates/"))
template_source = env.loader.get_source(env, template_file)[0]
parsed_content = env.parse(template_source)
variables = meta.find_undeclared_variables(parsed_content)
'''
# For each variable in the template, generate an input field in the web form (sorted alphabetically)
for v in variables:
vars()[v] = StringField(v)
submit = SubmitField("Submit")
# Create the form object to be rendered
form = FormGenerator()
return render_template("form.html", template_name=template_name, form=form)
@app.route("/upload", methods=["GET", "POST"])
def upload():
'''
Upload a file to the templates folder
'''
# Display the upload page
if request.method == "GET":
return render_template("upload.html")
# Upload the selected file to the templates folder
if request.method == "POST":
f = request.files["file"]
f.save(os.path.join(TEMPLATE_FOLDER, secure_filename(f.filename)))
return redirect("/")
if __name__ == "__main__":
# Run the development server on port 80 when called directly
app.run(debug=True,host="0.0.0.0", port="80")