0

I want to display the chemical formula of compound with subscript. I have a list of compounds and few of them should be written using subscript. I wrote the following code:

def contains_number(string):
    new_string = ''
    int_str_list = list(map(str, list(range(9))))
    for item in string:
        if item in int_str_list:
            new_string += '<sub> '+item+' </sub>'
        else:
            new_string += item
    return new_string

This code works and when I pass string like Fe2O3, I get the output like: Fe<sub>2</sub>O<sub>3</sub> which is what I want.

However, when I pass this as a context variable to Django template, it is not rendered as Fe2O3 but as text Fe<sub>2</sub>O<sub>3</sub> .

Since I am new to Django, I am missing something, I know.

How can I fix this?

5
  • Those two outputs look the same to me, whats different? What code are you using to pass as context? Commented Dec 3, 2015 at 13:18
  • That was my thought exactly. It is rendered in browser, however as, Fe<sub>2</sub>O<sub>3</sub> ., which if put into plain html will give the subscripted text. Commented Dec 3, 2015 at 13:20
  • 2
    You should probably turn escape off in django template: docs.djangoproject.com/en/1.8/ref/templates/builtins/… Commented Dec 3, 2015 at 13:22
  • @stellasia : Wonderful, that was the culprit. Thank you very much. Please post it as your answer so that I can accept it. Commented Dec 3, 2015 at 13:27
  • 1
    if the item is user input, you should escape it first, then you can disable autoescape. Commented Dec 3, 2015 at 13:31

3 Answers 3

2

Django autoescapes template variables. If you look at the source of the generated output, you will see something like &lt;sub&gt;2....

Do not just turn autoescaping if the parameter string is user generated input!

Auto-escaping prevents XSS attacks, so turning it off might fix your problem, but can lead to a security vulnerability if you don't know exactly what you are doing.

from django.utils.html import escape
from django.utils.safestring import mark_safe


def contains_number(string):
    new_string = ''
    for item in string:
        if item.isdigit():
            # we know item is a number, so no need to escape it
            new_string += '<sub> '+ item +' </sub>'  
        else:
            new_string += escape(item)
    # we built new_string from safe parts, so we can mark it as
    # safe to prevent autoescaping
    return mark_safe(new_string)
Sign up to request clarification or add additional context in comments.

Comments

2

... or you can use safe filter:

{{ your_text|safe }}

I believe in most cases it's safer than autoescape blocks (no risk you'll leave unescaped something you have to escape).

Comments

1

Your problem is related to HTML tag escape. Turn the autoescape off in the django templates and it should work fine:

{% autoescape off %}
    {{ you_text }}
{% endautoescape %}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.