Home > front end >  Dynamically create Links from List in Flask
Dynamically create Links from List in Flask

Time:11-06

I am trying to dynamically create a list of links to files in a static folder and failing with nested {{ {{ }} }} that would be logically required.

A Flask server has files in

/Static/FileFolder

they are collected in a list with

FileList = []
    
for path in os.listdir(FileFolderPath):
    if os.path.isfile(os.path.join(FileFolderPath, path)):
        Filelist.append(path)

the Link is built with

return render_template('list.html', FileList = FileList)

and the Html has this piece

{% for item in FileList %}

<li><a href=" {{url_for('static', filename=' {{item}} ')  }}">{{item}}</a>  </li>

{% endfor %}

which fails as

filename=' {{item}} '

does not give me the url for the link to the file but just a nonsense link to

http://127.0.0.1:5020/static/ {{item}} 

which has the wrong folder and name. So how can i give the correct folder and place a link to a {{item}} inside a {{ }} used for url_for ?

CodePudding user response:

You don't need the double curly braces inside a block that is already jinja templated

templates/lists.html

{% for item in FileList %}

<li><a href=" {{ url_for('file', variable=item)  }}">{{item}}</a>  </li>

{% endfor %}

app.py

import os
from flask import Flask, render_template


app = Flask(__name__)


def funk():
    FileList = []
    FileFolderPath = '.'

    for path in os.listdir(FileFolderPath):
        if os.path.isfile(os.path.join(FileFolderPath, path)):
            FileList.append(path)
    return FileList


@app.route('/')
def hello_world():
    FileList = funk()
    return render_template('./list.html', FileList = FileList)


@app.route('/<variable>/')
def file(variable):
    return variable

terminal

export FLASK_APP=app.py
flask run

tree

.
├── app.py
└── templates
    └── list.html

CodePudding user response:

What if you only use once the jinja2 markdown as it follows:

{% for link in links %}

        <li><a href="/static/{{ link }}">{{ link }}</a>  </li>

{% endfor %}

Another option, but this mainly depends on what you're trying to accomplish, is adding another route to your app.py

@app.route('/static/<page>')
def get_link(page):
    return f'{page}'

and afterwards in your html file:

<li><a href="{{ url_for('get_link', page=link) }}">{{ link }}</a></li>

Also, you might want to consider using the PEP8 naming guidelines > https://peps.python.org/pep-0008/#type-variable-names

CodePudding user response:

As already mentioned, you can pass the variable containing the relative path to the file directly without brackets and quotation marks.

Note that you need the full relative path inside the static folder to reference the file with url_for('static', filename=...) .

The following example uses the pathlib module to implement your requirements.

from pathlib import Path

@app.route('/')
def index():
    # ./static/path/to/folder/
    p = Path(app.static_folder, 'path', 'to', 'folder')
    filenames = [x.relative_to(app.static_folder) for x in p.iterdir() if x.is_file()]
    return render_template('index.html', **locals())
<ul>
    {% for filename in filenames -%}
    <li><a href="{{ url_for('static', filename=filename) }}">{{ filename }}</a></li>
    {% endfor -%}
</ul>
  • Related