I am having some problems using Python to generate an html document. I am attempting to create an HTML list of a directory tree. This is what I have so far:
def list_files(startpath):
for root, dirs, files in os.walk(startpath):
level = root.replace(startpath, '').count(os.sep)
if level <= 1:
print('<li>{}<ul>'.format(os.path.basename(root)))
else:
print('<li>{}'.format(os.path.basename(root)))
for f in files:
last_file = len(files)-1
if f == files[last_file]:
print('<li>{}</li></ul>'.format(f))
elif f == files[0] and level-1 > 0:
print('<ul><li>{}</li>'.format(f))
else:
print('<li>{}</li>'.format(f))
print('</li></ul>')
It seems to work well if there is only the root directory, one level of sub-directories and files. However, adding another level of sub-directories causes there to be problems (because the close tag isn't input enough times at the end I think). But I'm having a hard time getting my head around it.
If it can't be done this way, is there an easier way to do it? I'm using Flask but I'm very inexperienced with templates so perhaps I'm missing something.
You could separate the directory tree generation and its rendering as html.
To generate the tree you could use a simple recursive function:
def make_tree(path):
tree = dict(name=os.path.basename(path), children=[])
try: lst = os.listdir(path)
except OSError:
pass #ignore errors
else:
for name in lst:
fn = os.path.join(path, name)
if os.path.isdir(fn):
tree['children'].append(make_tree(fn))
else:
tree['children'].append(dict(name=name))
return tree
To render it as html you could use jinja2's loop recursive feature:
<!doctype html>
<title>Path: {{ tree.name }}</title>
<h1>{{ tree.name }}</h1>
<ul>
{%- for item in tree.children recursive %}
<li>{{ item.name }}
{%- if item.children -%}
<ul>{{ loop(item.children) }}</ul>
{%- endif %}</li>
{%- endfor %}
</ul>
Put the html into templates/dirtree.html file.
To test it, run the following code and visit http://localhost:8888/:
import os
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def dirtree():
path = os.path.expanduser(u'~')
return render_template('dirtree.html', tree=make_tree(path))
if __name__=="__main__":
app.run(host='localhost', port=8888, debug=True)
Related
I am trying to use <%include /> tag in mako template, but getting exception. I have all the files in the same directory. Can someone help me figure out what am I missing here?
$cat sample1.py
from mako.template import Template
fn = "sample1.txt"
templateDef = open(fn, "r").read()
t = Template(templateDef).render()
print(t)
$cat sample1.txt
<%include file="header.html"/>
hi
<%include file="footer.html"/>
$cat header.html
<html>
header
</html>
$cat footer.html
<html>
footer
</html>
This is the error I get:
$python3 sample1.py
mako.exceptions.TemplateLookupException: Template 'memory:0x2b80733bc3c8' has no TemplateLookup associated
Syntax wise I do not see any issue. Even though all the files are in the same directory, I can't get it to work. Any help?
Use TemplateLookup function
a=TemplateLookup(directories=[‘dirname’])
Temp=a.get_template(‘filename’)
Print(Temp.render())
Visit
https://docs.makotemplates.org/en/latest/usage.html#mako.lookup.TemplateLookup
I would like to build a simple web application that able to display the results of parsing YAML files using python and Flask. I've been written the code and it works, but the results not the same as expected.
Here's my code:
import yaml
from flask import Flask, request, render_template, redirect, url_for
#from pathlib import Path
app = Flask(__name__)
#app.route('/', methods=['GET','POST'])
def my_form_post():
#path=Path('/Users/Devie Andriyani/EditFlask/categories.yaml') # set the path to your file here
#if not path.exists():path.touch()
if request.method == 'POST':
#with open(path, 'w') as f:
#f.write(request.form.get('Text Area',None))
return redirect(url_for('my_form_post'))
#with open(r'C:\Users\Devie Andriyani/EditFlask/categories.yaml') as f:
#my_dict = yaml.safe_load(f)
a_yaml_file = open("categories.yaml")
parsed_yaml_file = yaml.load(a_yaml_file, Loader=yaml.FullLoader)
print(parsed_yaml_file["countries"])
print(parsed_yaml_file["sports"])
return render_template('index.html')
if __name__ == '__main__':
app.debug = True
app.run()
And here's my HTML code:
<!DOCTYPE html>
<head>
<title>Hello</title>
</head>
<body>
<form action="" method="POST">
<p>Text Area</p>
<p><textarea name="Text Area" rows="20" cols="50" value={{categories}}></textarea>
</p>
<input type="submit">
</form>
</body>
</html>
And here's my YAML file:
sports:
- soccer
- football
- basketball
- cricket
- hockey
- table tennis
countries:
- Pakistan
- USA
- India
- China
- Germany
- France
- Spain
And here's the result:
I want the results of parsing show on the text area
You opened the file, saved it in a variable, but you didn't pass that to the front-end. You just print it, that why it is printing in the console. You have to pass this to the frontend.
parsed_yaml_file = yaml.load(a_yaml_file, Loader=yaml.FullLoader)
# print(parsed_yaml_file["countries"]) # this will print in console not in frontend
# print(parsed_yaml_file["sports"]) # this too
return render_template('index.html', yml = parsed_yaml_file)
Here I passed the file content parsed_yaml_file to the frontend with the name yml. So we can access this in the frontend now. But one problem we have. yaml.load will return a dictionary. And if you want to display as a dictionary, then no worries. But if you want to display as YAML format itself, then you should not convert it into yaml. You directly pass the file a_yaml_file.
Suppose if you want yaml output, (hope you passed yml = a_yaml_file) then in frontend you have to use pre tag.
<pre>{{ yml }}</pre>
If you want a dictionary, (pass yml = parsed_yaml_file) then just use this in frontend
{{ yml }}
I am new to using Jinja2 and am trying to render an html file from several strings and lists.
Lets say I have a File path, a term, and a sentence.
Using these I want to create an html file which has the file path as well as the two sentences where the the word is bolded if it matches the term.
I.e.
file_path is "/usr/bin/local/cheese.txt"
term is "cheese"
sentence is "i am cheese cheese i am"
I want to create and html file that looks like this
<html>
<body>
<h2>Search results for <b>cheese</b> in the file</h2>
<p>/usr/bin/local/cheese.txt<br>
I am <b>cheese</b> <b>cheese</b> I am<br><br>
</body>
</html>
I have been trying to use Jinja2 but am having trouble creating an HTML file by specifying the formatting.
Here is what I have so far:
import jinja2
from jinja2 import Environment, FileSystemLoader
def render_template(template_filename, context):
return TEMPLATE_ENVIRONMENT.get_template(template_filename).render(context)
file_path = "/usr/bin/local/cheese.txt"
term = "cheese"
sentence = "i am cheese cheese i am"
context = {
'h2': "Search results for <b>" + terms + "</b>",
'urls': file_path, # for making the file path tag - not sure if right
'bold': term, # Do not think this is correct
'paragraph': sentence ## Do not think this is correct at all.
}
output = template.render_template("temp.html", context)
I do not think this is correct, but if someone who knows Jinja2 please tell me how to format this correctly I would be most grateful.
Please let me know if you need any more information.
Thank you for your time.
That's an example of your code in jinja2:
Python:
from jinja2 import Template
def render_template(template_filename, context):
with open(template_filename) as file_:
template = Template(file_.read())
return template.render(context)
file_path = "/usr/bin/local/cheese.txt"
term = "cheese"
sentence = "i am cheese cheese i am"
if term in sentence:
sentence = sentence.replace(term, '<b>%s</b>' % term)
context = {
'h2': "Search results for <b>" + term + "</b>",
'urls': file_path,
'bold': term,
'paragraph': sentence
}
output = render_template(your_template, context)
print(output)
Your template:
<html>
<body>
<h2>{{ h2|safe }}</h2>
<p>{{ urls }}}}<br>
{{ paragraph|safe }}<br><br>
</body>
</html>
So, I am using flask and I have some lines of code written that will store some values in a list. I want to display these values in the list on a web page and I have done the following:
#Python code to generate values for the list
app = Flask(__name__)
#app.route("/")
def main():
list1 = ['a', 'b']
return render_template("main1.html", var=list1)
if __name__ == "__main__":
app.run()
If i run the following program, a bunch of errors are displayed and it says Internal Server Error on the webpage. Any inputs regarding how I can display the list on the web page will be appreciated.
Thanks.
When you use render_template,flask will look for templates in the templates folder,this folder is next to that module.So your package should be like this:
/app.py
/templates
/main1.html
If main1.html does not exist,you can't visit the web page,here is an example.
<!doctype html>
<title>Hello from Flask</title>
{% for i in list1 %}
<h2>{{ i }}</h2>
{% endfor %}
See more details from rendering-templates .
I'm trying to display images located in a folder which is not the default static folder.
My template looks like:
{% extends "layout.html" %}
{% block body %}
Albums
{% for album in albums %}
<img src="{{ album ['ThumbPath'] }}">
{% endfor %}
{% endblock %}
The generated HTML looks like:
<!doctype html>
<title>iPhoto</title>
<link rel=stylesheet type=text/css href="/static/style.css">
<div class=page>
<h1>iPhoto</h1>
<img src="/Users/Darrell/Pictures/iPhoto Library/Thumbnails/2013/08/09/20130809-180444/t264vvMaQM+GJosBP+4q+Q/_DSC1225.jpg">
<img src="/Users/Darrell/Pictures/iPhoto Library/Thumbnails/2013/08/09/20130809-181030/urU3jqSKRgGNNP1MjKhpvg/_DSC1268.jpg">
<img src="/Users/Darrell/Pictures/iPhoto Library/Thumbnails/2013/08/09/20130809-181037/1zYyNYReRg+Sizx8v4BUkw/_DSC0923.jpg">
<img src="/Users/Darrell/Pictures/iPhoto Library/Thumbnails/2013/08/09/20130809-181038/sKzEEB3jSf6GBs2heQIviA/Kelly.jpg">
</div>
How can get the images to be rendered on the generated webpage.
The path to the image is correct.
It is no option to copy all images to the static folder.
Darrell
Look like you have file system path instead site. When you start resource with / then path will start from site root (absolute path for site, without slash or with ./ or ../ is relative) for example if you have site http://test.com then / will be http://test.com/ or /test will be http://test.com/test. You can set path with specific protocol protocol:// or identical for current site // for another sites. You always can found errors with wrong (full) urls in your browser error console.
To get access to file system you must use file:// protocol and you urls will be like file:///Users/Darrell/Pictures/.... But it will work only for your computer and can have security issues. You also can set symbolic link for this files to static folder and this resolve security issues, but not resolve issue with only your computer. To completely resolve this issue better publish this files to your application or on public (private) web servers for images or another static.
So here is my project path. I wrote a simple function that would work by allowing it to render on the webpage. I am not a 100% sure if it would work once deployed, so I will update if it does work when deployed.
<img alt="" src="{{ url_for('send_file', filename=image_url) }}" id ="img"/>
This is the code of the HTML element and here is its corresponding code in Python on the server side.
def getImageName(x):
"""
Dealing with Unix Path names and Windows PathNames
"""
if platform.system() == 'Linux':
return x[x.rfind("/")+1:]
return x[x.rfind("\\")+1: ]
def getFolder(x):
y = []
if platform.system() == 'Linux':
y = x.split("/")
else:
y = x.split("\\")
# print(y)
cat_name = ""
if "roomImage" in x:
cat_name+="roomImage/" + y[-2]
elif "lobbyImage" in x:
cat_name+="lobbyImage"
elif "miscImage" in x:
cat_name += "miscImage/" + y[-2]
elif "washroomImage" in x:
cat_name += "washroomImage"
else:
cat_name += "facadeImage"
return cat_name + "/"
#app.route("/send_file/<filename>")
def send_file(filename):
return send_from_directory(app.config["UPLOAD_FOLDER"] +"/" + getFolder(filename) , getImageName(filename))
This works for the most part.
By the way, image_url is supposed to the be the absolute path of the image that you can pass as an argument to the Jinja2 template via render_template like so:
return render_template("/contentpage.html",image_url=imgurl)
Don't forget to import send_from_directory and set app.config["UPLOAD_FOLDER"] to the appropriate directory. This isn't the most efficient way to do it