I have a bunch of files in a directory that I wish to render and serve to the user, but have been unable to. Going to the path always returns just the 'page_template.htm'
and not the rendered file. Here’s my code:
from flask import Flask, request, render_template, send_from_directory # Instantiate the Flask app app = Flask(__name__) app.config.from_object(__name__) pages = FlatPages(app) @app.route("/") @app.route("/index") def index(): return render_template('index.html') @app.route("/Special_Data/<path:path>") def page(path): page = send_from_directory('Special_Data', path) return render_template('page_template.htm', page=page)
What I wish to do is to grab raw text files from the 'Special_Data'
directory and to render them into html files so they look nice, then send them to the user if they click on a link.
The files are in the directory 'Special_Data'
and the 'page_template.htm'
is in the 'templates'
directory.
Where am I going wrong?
Advertisement
Answer
The following example shows you how you can use FlatPages to list, display and offer files for download. The markdown code is rendered beforehand and integrated into the specified or the default template.
from flask import Flask from flask import render_template, send_file from flask_flatpages import FlatPages from io import BytesIO import os app = Flask(__name__) # Optional configuration here! pages = FlatPages(app) # ... # List all available pages. @app.route('/contents') def contents(): return render_template('contents.html', pages=pages) # Display the rendered result. @app.route('/page/<path:path>') def page(path): page = pages.get_or_404(path) template = page.meta.get('template', 'flatpage.html') return render_template(template, page=page) # Download the rendered result. @app.route('/download/<path:path>') def download(path): page = pages.get_or_404(path) template = page.meta.get('template', 'flatpage.html') return send_file( BytesIO(str(render_template(template, page=page)).encode()), as_attachment=True, attachment_filename=f'{os.path.basename(path)}.html' )
templates/contents.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <ul> {% for page in pages %} <li> [<a href="{{ url_for('download', path=page.path) }}">Download</a>] - <a href="{{ url_for('page', path=page.path) }}">{{ page.title }}</a> </li> {% endfor %} </ul> </body> </html>
templates/flatpage.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>{{ page.title }}</title> </head> <body> {{ page }} </body> </html>
pages/Special_Data/ncs1.html
title: Hello published: 2010-12-22 Hello, *World*! Lorem ipsum dolor sit amet
If you want to use a different template for rendering, you can define one within the metadata based on the file name. Add the following below published and a suitable template within the templates folder.
template: mytemplate.html