On Thu, Sep 8, 2011 at 4:51 AM, Ben Sizer <[email protected]> wrote:
> On Sep 1, 2:32 am, cd34 <[email protected]> wrote:
>> Also, I use deform with both Mako and Jinja2,
>> and unless you need to change the widgets, it doesn't really matter
>> much that the templates use chameleon. I've written several projects
>> and except for one minor case, haven't modified the templates.
>
> That's what I had hoped would be the case, due to the similar syntax.
> But when I actually tried it, the change from Chameleon to Mako
> started escaping all the HTML that I was injecting into the template,
> including rendered forms, which made a lot of my code useless. :)
>
> Thanks also for your example code. Whether or not I use deform, I will
> probably switch to Mako and so the summary of all the things I need to
> change is very helpful.

It's important to understand how this smart escaping works. It was
built into the late generation of template engines to avoid injecting
unexpected HTML markup into templates, especially those coming
directly from user input. Site developers should escape all input
data, but sometimes they forget, or markup is found in a database
field where nobody anticipated it, etc.  Mako, Pyramid, and WebHelpers
have all converged on the MarkupSafe package, which replaced their
previous individual systems. I haven't used Chameleon so I don't know
how it's configured in Pyramid, but I assume it should be escaping
like Mako.

The system escapes all strings except those which have been explicitly
marked as preformatted. The marker is an '.__html__' method on the
object, which is called instead of '.__str__'. Normal string objects
do not have this method, but the subclasses ``markupsafe.Markup`` and
``webhelpers.html.literal`` do.  The marker is a method rather than a
base class so that any library can provide its own implementation
without depending on anything external. So, using WebHelpers:

    literal(u"My <strong>safe</strong> string.")    =>  mark the
string preformatted as-is
    escape(u"My <strong>unsfae</strong> string.")   => escape the
string and mark it as preformatted

Mako implements the escaper as a default filter, meaning it's applied
by default to every value that's inserted into the template. The
"${var | n}" syntax disables the default filter, which allows the
string to remain as-is even if it's not marked. So you can do this.
But in principle it's better to mark the string as early as possible,
to maintain the distinction of safe vs unsafe strings throughout the
program. The WebHelpers form helpers automatically produce marked
strings. Other libraries should do the same (now that MarkupSafe has
become the de facto standard in Pylons/WSGI circles), but maybe they
don't.

Mako automatically marks the return values from its '%def' methods,
because literal HTML in the template is presumed to be safe. This has
the side effect of escaping any unmarked strings embedded in the
return value.

Normally when marked and unmarked strings are mixed in an expression,
the unmarked strings are escaped and the final result is marked.
Markup/literal do this by overriding the '+' operator to take control
of the evaluation. However, in a few unavoidable cases due to Python's
language rules, an unmarked component takes control of the expression,
and the final result is a regular string (unmarked), which will
therefore be escaped when used in a template. The solution to this is
to wrap the expression in `Markup()` or `literal()`, or to use the
convenience functions which take care of this ; e.g.

     webhelpers.html.lit_sub(my_re_regex, ...)

instead of:

     my_re_regex.sub(...)

-- 
Mike Orr <[email protected]>

-- 
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/pylons-discuss?hl=en.

Reply via email to