Django's template language is not being properly interpreted in the text file loaded into the Django template

I have a function that loads text files for reading.
These files have names like tuto_01.txt, tuto_02.txt, etc.

def tuto(request, tuto_id):
    # Get the current directory
    rep_cour = os.getcwd()
    # Construct the path to the txt file
    file_path = rep_cour + f"/api/articles/tuto_0{tuto_id}.html"
    print(file_path)
    # Check if the file exists
    if not os.path.isfile(file_path):
        return HttpResponseNotFound("Page not found")
    # Open and read the content of the txt file
    with open(file_path, 'r') as file:
        content = file.read()
    # Construct the context
    context = {
        'content': content,
        'tuto_id': tuto_id,
    }
    # Render the template with the context
    return render(request, 'tuto.html', context)

my print(file_path) it’s ok

I send the content as context to the tuto.html template:

{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block content %}
<h1>Tutorial {{ tuto_id }}</h1>
<div>
    {{ content }}
</div>
{% endblock %}

Here’s an example of a txt file:

 <div class="row ">
      <div class="col-8">
        <img class="img-fluid img-thumbnail" src="{% static 'img/appli_django_01.png' %}" alt="..." />
        <h2>Title</h2>
        <p>All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy.All work and no play makes Jack a dull boy <img class="img-fluid img-thumbnail" src="{% static 'img/appli_django_01.png' %}" alt="..." /></p>   
      </div></div>
  My issue is that the syntax of Django's template language is not being properly interpreted in the text file loaded into the Django template, tuto.html. For example, the image called in the text file is not being displayed. Thank you for your assistance.  There might be an issue with my logic.
  
  thank for help

What is the reasoning behind reading each tutorial from a text file?

When Django templates come across {{ content }} this assumes a plain text string and not HTML or Django Templates. So you could add the safe filter to the content rendering to render the HTML, but if you want to render the Django templates then this would need to be done in the view, reading the file is not sufficient.

However, if reading the tutorials from the text file you could solve this by just further extending your Django template files.

The solution really depends on the answer to the first question I asked :slight_smile:

In addition to the correct response above, there are at least two ways to resolve this.

  1. Place these text templates in a template directory and use the include tag to include that into the template being rendered.

  2. Use the render_to_string function to create rendered html from the template file, and include that in your context, also using the safe filter.

Either of these solutions should do what you’re attempting to do here.

thank Ken and nano,
I have modified the function.

from django.template.loader import render_to_string
def tuto(request, tuto_id):
    rep_cour = os.getcwd()
    file_path = rep_cour + f"/api/articles/tuto_0{tuto_id}.html"
    print(file_path)    
    if not os.path.isfile(file_path):
        return HttpResponseNotFound(" Page non trouvé")
    with open(file_path, 'r') as file:
        content = file.read()
    
    tuto_html = render_to_string('tuto.html', {'content': content, 'tuto_id': tuto_id}, request=request)
    
    context = {
        'tuto_html': tuto_html,
        'tuto_id': tuto_id,
    }
    return render(request, 'tuto_index.html', context)
  in tuto_index
 {% extends 'base.html' %}
{% load static %}
{% block content %}
 {{ tuto_html|safe }} 
 {% endblock %}

the text file displays correctly , with css , in the template, but if I include the following in the text file
<img class="img-fluid img-thumbnail" src="{% static 'img/tuto_web_roue.png' %}" alt="..." />,

the page doesn’t load because the text file doesn’t support the Django template language. I have made the modification by changing the file extension from .txt to .html, but the problem remains the same. I can make absolute URL links, but it would have been nice if I could use Django tags to do various things in this files.

That is not correct. The extension of a file has no bearing on how it’s interpreted by the DTL.

The issue here is that you’re still trying to apply the content of the file as a string.

You need to render the text file, not an html file with a reference to the text file. In other words, your first parameter to the render_to_string needs to be the api/articles/tuto_01.html file, not some other template.

thank Ken,
I will put my head in an ice bath and try to look at your solution.

I have made some changes to my views.py. In addition to a menu that I build in my tutorial summary page (tuto_index),

 # menu in tuto_index
def tuto_index(request):    
    rep_cour = os.getcwd()
    tuto_files = glob.glob(rep_cour + "/api//templates/articles/tuto_*.html")
    tuto_ids = [int(os.path.basename(file)[5:7]) for file in tuto_files]
    context = {
        'tuto_ids': tuto_ids,  }    
    return render(request, 'tuto_index.html', context)
def tuto(request, tuto_id):    
    file_path = f"articles/tuto_{str(tuto_id).zfill(2)}.html"     
    content = render_to_string(file_path, request=request)
    # Construction du contexte
    context = {
        'content': content,
        'tuto_id': tuto_id,
    }    
        return render(request, 'tuto.html', context)

I have set the direct access to the files that I load (they are in HTML now) as the first argument of render_to_string. It works if I don’t put a Django template inside the loading html files, text and CSS are good, but if I put a template tag, I get this error message :
Invalid block tag on line 9: ‘static’. Did you forget to register or load this tag?

Every template being rendered and using the static tag needs to load the definition of static in the template.

thank Ken, I added the static template tag at the beginning of the files and it works.

Glad you sorted it and apologies I didn’t get back to reply sooner.

Although I am still a bit confused by the loading of individual files, and then doing the rendering twice.

My personal solution would be to continue to use template inheritance like so:

view:

def tuto(request, tuto_id):    
    context = {
        'tuto_id': tuto_id,
    }    
    return render(request, 'tuto_{str(tuto_id).zfill(2)}.html', context)

then move the individual tutorial files next to tuto.html in your templates directory and wrap the content as follows: (I have used the example from your first post)

{% extends 'tuto.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block tuto_content %}
     <div class="row ">
      <div class="col-8">
        <img class="img-fluid img-thumbnail" src="{% static 'img/appli_django_01.png' %}" alt="..." />
        <h2>Title</h2>
        <p>All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy.All work and no play makes Jack a dull boy <img class="img-fluid img-thumbnail" src="{% static 'img/appli_django_01.png' %}" alt="..." /></p>   
      </div></div>
{% endblock %}

And finally tuto.html would be modified as follows:

{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block content %}
<h1>Tutorial {{ tuto_id }}</h1>
<div>
{% block tuto_content %}
{% endblock tuto_content %}
</div>
{% endblock content %}

Thank you Nano for your answer, I will try your solution.

Note: While this is close to what I suggested as #1 above, I had a slightly different idea in mind:

The view:

Then, in the tuto.html template:

{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block content %}
<h1>Tutorial {{ tuto_id }}</h1>
<div>
  {% include tuto_template %}
</div>
{% endblock content %}

The key limitation of this technique, however, is that these files need to be in the template directory. If you’re looking at doing this with user-editable files, something that would likely reside in your MEDIA_DIR, then this is not an appropriate approach. (It’s not clear from this post whether this is an issue or something that needs to be accounted for.)

This is true.

If we had an answer for why @jungleghost was choosing to load files into the view to render them, then this would clarify which solution would be most appropriate

To answer Kent, I would like to clarify that the files are not editable. These are articles that I will write gradually and put in the template folder of the application, then from the summary page of these articles I load them via a link. It’s quite basic.

Initially, I thought about going through the admin to insert the articles into the database, it’s much simpler, I even tried the CKeditor module, but I am not satisfied with the image management and the CSS. But this is another topic. Anyway, I thank you for your brilliant answers. Good evening (…or good day!)”

1 Like