Phil
Phil

Reputation: 14641

Pyramid - mako: Escape HTML partially

I am using Mako templates to create a web page.

There is a section in which I prevent html escaping using | n. However, inside, I also need to show some user generated entries for which I need to escape the HTML on the view side of the apps.

What is the way to go with Pyramid for this?

I know there is CGI escaping but it does not seem as good as Mako's own and I would like to use that.

currently I have:

from pyramid.compat import escape

escape(str)

Thank you!

Upvotes: 2

Views: 2469

Answers (4)

Matt Goldworm
Matt Goldworm

Reputation: 65

I use markdown (and pagedown in Javascript) for some limited markup as well as some HTML to allow users to customize their inputs.

Before saving or displaying the custom user markup, I clean up the HTML with:

from html5lib import sanitizer
from html5lib import html5parser, serializer, treebuilders, treewalkers

# This sanitizer translates all the troublesome tokens
def sanitize2(text):
    if (text is None) or isinstance( text, ( int, long ) ):
        return text
    sanobj                      = sanitizer.HTMLSanitizer
    sanobj.strip_tokens         = True
    sanobj.lowercaseElementName = True
    sanobj.lowercaseAttrName    = True
    hparser                     = html5parser.HTMLParser(tree = treebuilders.getTreeBuilder('dom'), tokenizer=sanobj)
    dommodel                    = hparser.parse(text)
    serobj                      = serializer.htmlserializer.HTMLSerializer(sanitize = False)
    outstr                      = ''.join(serobj.serialize(treewalkers.getTreeWalker('dom')(dommodel)))
    return outstr

Then, I have a custom pyramid filter to actually display it:

import markdown

def jmarkdown(text):
    return markdown.markdown(text)

This makes "| jmarkdown" work!

Upvotes: 0

kevinstueber
kevinstueber

Reputation: 2956

I thought I would throw my 2 cents in here since I was looking to solve a similar issue. In my case I'm very new to Python and Pyramid and I am modifying the Single File Tasks Tutorial to create a (very) simple blog.

My post content was saved as a string in a sqlite database. The problem was that when the content string was output to the template html tags were appearing as plain text.

So rather than:

enter image description here

I was getting:

enter image description here

Adding the | n filter solved my issue. HTML content now displays correctly in my post bodies.

My template (.mako) for the list of posts:

# -*- coding: utf-8 -*- 
<%inherit file="layout.mako"/>

<ul id="posts">
% if posts:
  % for post in reversed(posts):
  <li>
    <span class="name">${post['name']}</span> 
    <span class="content">${post['content'] | n}</span>
  </li>
  % endfor
% else:
  <li>Sorry, no posts...</li>
% endif
</ul>

and the view_config:

@view_config(route_name='list', renderer='list.mako')
def list_view(request):
    rs = request.db.execute("select id, name, content from posts")
    posts = [dict(id=row[0], name=row[1], content=row[2]) for row in rs.fetchall()]
    return {'posts': posts}

This answer helped me out.

I hope this helps someone.

Upvotes: 3

webjunkie
webjunkie

Reputation: 1184

The webhelpers package offers a escape function that might help. From the docs:

webhelpers.html.builder

HTML Builder provides:

an HTML object that creates (X)HTML tags in a Pythonic way.

a literal class used to mark strings containing intentional HTML markup.

a smart escape() function that preserves literals but escapes other strings that may accidentally contain markup characters (“<”, “>”, “&”, ‘”’, “’”) or malicious Javascript tags. Escaped strings are returned as literals to prevent them from being double-escaped later.

Upvotes: 2

Mark Hildreth
Mark Hildreth

Reputation: 43071

According to the pyramid docs, pyramid.compat.escape provides cgi.escape (html.escape on Python 3).

According to the mako docs, the escape functionality is provided by markupsafe.escape(x). One thing to keep in mind that might be helpful is that MarkupSafe will look for an __html__ method on the object it is escaping, and if it finds it, it will call that method and use the results as the escaped string. This might allow you some flexibility in how certain items are escaped.

You can either use one of these, or another option is (if possible) to change your template so that the escaping actually does happen in the template rather than the view.

Upvotes: 3

Related Questions