Skip to content
Advertisement

Flask: unable to serve rendered pages from specific directory

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
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement