Search code examples
pythonhtmltemplatesjinja2fastapi

Using Jinja templates to display products from a database on a website


There is a function that takes data from the database and creates html code with the required number of buttons, This code needs to be embedded on the main page

The function returns the following code

buttons = """
<form method="post" action="/all/1">
    <button type="submit" id="button"
        <div>
            <p id="1_name" >name</p>
            <p id="1_description">description</p>
        </div>
    </button>
</form>
"""

If you use this method, the html code is inserted as plain text and the buttons are not displayed

Python

@router.get("/")
async def test(request: Request):
    buttons = buttons()
    return templates.TemplateResponse("home.html", {"request": request, "buttons": buttons})

HTML

<div id="all">
    {{buttons}}
</div>

Also, not allowed inserting via

<div id="all">
    {% include="some_file.html" %}
</div>

Solution

  • By default Jinja2 is configured to autoescape HTML special characters to prevent XSS vulnerabilities.

    You shouldn't be using code to generate HTML. Use the templating options Jinja2 give to generate HTML.

    If you need to create an N amount of buttons you can create a Jinja2 template which will create N buttons from 1 to N.

    main.py

    @router.get("/")
    async def test(request: Request):
        buttons = buttons() # returns an `int` (Eg. 3)
        return templates.TemplateResponse("home.html", {"request": request, "buttons": buttons})
    

    home.html

    <form method="post", action="all/1">
        {% for i in range(1, buttons+1) %}
        <button>
            <div>
                <p id="{{ i }}_name">name: {{ i }}</p>
                <p id="{{ i }}_description">description: {{ i }}</p>
            </div>
        </button>
        {% endfor %}
    </form>
    

    If for some reason you still don't want to use Jinja2 templating. You have to configure Jinja2 to not autoescape special HTML characters

    You can either manually escape the characters with the safe filter

    <div id="all">
        {{ buttons | safe }}
    </div>
    

    or you can set it to all your templates by default:

    templates = Jinja2Templates(directory="templates", autoescape=False)

    You can find more Jinja2 environment options here.