n33
n33

Reputation: 433

How to interpret/render template tags as HTML from Django database

I'm trying to add posts with images from Django admin site, but the safe/autoescape-off filter cannot interpret Django's template tags.

My input and page look like: enter image description here enter image description here

"copy image address" gives http://127.0.0.1:8000/%7B%%20static%20'post/image.jpg'%20%%7D

My view inherits from a generic ListView.

My base.html and post_list.html:

<!DOCTYPE html>
{% load static %}
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div style="color: red;">
      <a href="{% url 'admin:index' %}">admin</a>
      {% block contents %}
      {% endblock %}
    </div>
  </body>
</html>

{% extends 'post/base.html' %}
{% block contents %}
{% for post in object_list %}
  {% autoescape off %}{{ post.text }}{% endautoescape %}
  {{ post.text|safe }}
{% endfor %}
{% endblock %}

Upvotes: 2

Views: 1669

Answers (1)

neruson
neruson

Reputation: 31

You can't do what you're trying to do directly in the template. Django templates are made up of "nodes" that are later resolved into strings. Nodes using the {{ variable }} syntax always return a string: even if you use the safe filter, Django will not try to convert your post.text string into nodes to be rendered by the templating engine.

You could potentially work around this in the view by manually rendering your text as a Django template:

from django.template import Template

class MyListView(ListView):

    #...your existing code

    def get_context_data(self, **kwargs):
        context = super(MyListView, self).get_context_data(**kwargs)
        for post in context["object_list"]:
            post.rendered_text = Template(post.text).render(context)
        return context        

Then in your template:

{% for post in object_list %}
    {{ post.rendered_text|safe }}
{% endfor %}

But beware! This is a pretty bad idea from a security standpoint! The safe tag is already quite dangerous because it allows cross-site scripting attacks: anyone who has access to create a post can inject malicious Javascript that is displayed to the user. This extra rendering step is even more dangerous because it also gives access to the Django templating language and all the context of your view, which could have access to server-side secrets.

Upvotes: 2

Related Questions