The title says most of it. Python3.3 using a Pyramid app framework (-s starter)
Adding this code to the views.py controller:
from HTMLParser import HTMLParser
h = HTMLParser()
string = '<p>Hi there!</p>';
return dict( string=h.unescape(string) )
where return dict(..) is handed off to a template with a simple ${string} marker in it, the result in the web browser is always to show the angle brackets instead of rendering them as tags. I.e, the web page shows: <p>Hi there!</p>
I need to be able to pass user content (html with markup) through to the template for it to render inline. What more do I need to do?
The templating engine is escaping the variable, because just about every templating engine does that.
You need to structure your templates to not escape variables. This differs in mako , chameleon, etc.
IIRC, the starter scaffold uses Chameleon's .pt templates.
If that's what your'e using, this other StackOverflow question answers your question fully: Python Pyramid & Chameleon templating language escapes html
Related
I'm using django-pygmentes in order to highlight my code-blocks. I'm writing the contents with markdown and convert it to HTML in the view part. Everything is ok. Now, I want to implement the highlighting side. The Pygmentes package needs something like this in order to apply the colors:
<pre lang="python">...</pre>
But, it's what I get when I write a code block in my post:
<pre><code clas="language-python">...</code></pre>
Here is my markdown:
```python
print('Hey')
So, Pygments could not find the element. Is there any way to override any method and apply the changes?
UPDATED: Now, I've installed the pygments and added this extension to the markdown extensions. Here is my markdown and what it generates:
```{lang="python"}
print('Hello World')
Output:
<pre><code lang="python">
print('Hello World')
</code></pre>
Which is great, but there is no highliting yet.. :(
I also linked the classic styles.css file after running pygmentize -S default -f html -a .codehilite > styles.css and it linked properly.
Here is my custom markdown filter. The problem might be coming from this module:
from django import template
from django.template.defaultfilters import stringfilter
import markdown as md
register = template.Library()
#register.filter()
#stringfilter
def markdown(value):
return md.markdown(value, extensions=['markdown.extensions.fenced_code', 'markdown.extensions.attr_list'])
You can always revert to raw HTML. Simply insert the HTML directly into your document:
<pre lang="python">...</pre>
You could enable the CodeHilite Markdown extension, which uses Pygments to highlight code blocks. Python-Markdown will take the language set on the fenced code block and pass it to pygments for you. No need to use a Django app.
So long as you are using Python-Markdown version 3.3+ and you have enabled the attr_list extension, you can assign arbitrary key/value pairs directly to fenced code blocks (be sure to include the curly braces).
``` { lang=python }
However, that will still assign the attribute to the code tag, not the pre tag. Like this:
<pre><code lang="python">...
Also, note that the default behavior of generating <pre><code clas="language-python"> is the recommended way to designate the language of a codeblock in the HTML spec (see the second “example” ). One might consider it a bug for a tool to not recognize that method of designating the language for a code block.
I forgot to add the highlit extension in the custom filter module. Now, everything is working well. Thanks.
I have a string variable in a Python file that I am trying to render in my HTML template. The variable is called contacts, and in my template, I have {{contacts|default:"null"}}. From the documentation, it seems like that should work, but the template keeps coming up with the null keyword. I've scoured the documentation and found nothing. Probably a super simple thing I'm overlooking that has frustrated me to no end.
In the python file, I'm using an API to get a JSON and unloading it into a dictionary (don't know all the specific terms), where I then extract the value I need into a string:
...
dict_data = dict(json.loads(data))
contacts = str(dict_data["contact_count"])
Then in my HTML file:
<p class="spotbanner">
{{contacts|default:"null"}} spots left!
</p>
Is there something else I'm missing? Something super simple that I just don't understand about Django despite having used this method before? Happy to provide more information.
Poked around a teensy bit more and found an answer. For those like me:
It's not as simple as just rendering the variable. Django doesn't see it until you import the .py file into your views.py. Once you've done that, you'll need to create a context in the method that renders the page. For me, it finally worked once I added:
context = context = {"contacts":contacts}
Maybe a simple example might help you. Calling render_to_string to load a template HTML in Django.
Be aware the key name will map to the variable name in the HTML
from django.template.loader import render_to_string
rendered = render_to_string('my_template.html', {'foo': 'bar'})
# {{foo}} will show string 'bar' in HTML
Referral: https://docs.djangoproject.com/en/3.1/topics/templates/
Accordingly, by your cases, suppose we'll see something like
contacts = str(dict_data["contact_count"])
# if you want to show contact_count --> use {{contact_count}} in HTML
rendered = render_to_string('my_template.html', contacts)
I am looking for a way to render a variable that will be available in the context of the the page where the cms page will be rendered.
Ex:
I have in the context the logged in user and I also have the last transaction he made on the website.
I would like the text in the rich text field in Wagtail to be like this so that the marketing team can tweak the copy.
Hello ||firstname|| thanks for your purchase. ||productname|| will be
shipped to you soon. The expected delivery date is
||expected_delivery_date||
To be less confusing I replace the double brackets by double pipes to show that the templating system does not need to be django templates for those ones. Simple templating is enough maybe using https://docs.python.org/3.4/library/string.html#template-strings
I think I can achieve this by doing:
A stream field that would have blocks of rich text field and a custom block with the possible context variable they can use
A custom render function that would regex and replace the merge tags in the rich text block with the context values
Create a new filter for simple templating. ex: {{ page.body|richtext|simpletemplate }}
Is there any more obvious way or out of the box way to do templating from within a rich text field?
It would be clunky with a separate streamfield block for each inserted context variable. You'd have to override the default rendering which wraps elements in div tags. However I like that it is more foolproof for the editors.
I've done something like the custom rendering before, but with simple TextFields for formatting special offer code messages. Wagtail editors were given the following help_text to illustrate:
valid_placeholders = ['offer_code', 'month_price']
template_text = models.TextField(
_('text'),
help_text="Valid placeholder values are: {all_valid}. Write as {{{example}}}".format(
all_valid=", ".join(valid_placeholders),
example=valid_placeholders[0],
)
)
This rendered as Valid placeholder values are: offer_code, month_price. Write as {{offer_code}}.
Then in the view:
template_keys = [i[1] for i in Formatter().parse(template_text)]
…and continued rendering from there. Remember to validate the field appropriately using the above Formatter().parse() function too.
I used Django's template formatting rather than Python's string.format() because it fails silently, but you could go with string.format() if cleaned adequately.
The custom template filter would feel easiest to me, so I'd start with that approach and switch to a custom render function if I ran into hurdles.
I found an easier way to do this. I wanted my editors to be able to create pages with dynamic customization to the individual user. With this, my editors are actually able to put template variables into any type of content block as {{ var }} which works just like the Django templating language. For my use case, I am allowing my editors to create email content in the CMS, then pulling that to send the emails:
This is the function to call:
def re_render_html_template(email_body, context):
"""
This function takes already rendered HTML anbd re-renders it as a template
this is necessary because variables added via the CMS are not caught by the
first rendering because the first rendering is rendering the containing block,
so instead they are rendered as plaintext in content the first render, e.g., {{ var }}
Example:
input: <p>Hey {{ user_account.first_name }}, welcome!</p>
output: <p>Hey Brett, welcome!</p>
#param email_body: html string
#type email_body: str
#param context: context dictionary
#type context: dict
#return: html string
#rtype: str
"""
from django.template import Context
from django.template import Template
template = Template(email_body)
context = Context(context)
email_body = template.render(context)
return email_body
Then I call it like so:
email_body = render_to_string(template, context)
# need to re-render to substitute tags added via CMS
email_body = re_render_html_template(email_body, context)
I'm accepting Markdown and need to convert it to HTML to render securely in Django. Right now I'm accepting the form.cleaned_data and converting it to HTML with:
import markdown
html_body = markdown.markdown(body_markdown, safe_mode=True)
html_body = html_body.replace('[HTML_REMOVED]', '')
return html_body
In the template, I'm rendering it as :
{{ object.content|safe|capfirst }}
However if you post:
0;url=javascript:alert('hi');" http-equiv="refresh
The JS will render so XSS is possible.
django's built in safe template tag means that you are marking that variable as ok to output, i.e. you know that it's contents are safe:
safe: Marks a string as not requiring further HTML escaping prior to output.
Django by default escapes your template variables:
By default in Django, every template automatically escapes the output of every variable tag. Specifically, these five characters are escaped ...
but it won't strip the javascript away for you (it will just render it unusable), you need to do that manually with a template tag:
Strip javascript code before rendering in django templates
On the other hand, safe_mode on markdown strips any HTML in the text with [HTML REMOVED] as you've seen.
So removing safe should be enough to make it safe,
I'm hacking a quick and dirty python script to generate some reports as static html files.
What would be a good module to easily build static html files outside the context of a web application?
My goals are simplicity (the HTML will not be very complex) and ease of use (I don't want to write a lot of code just to output some html tags).
I found two alternatives on my first goolge search:
markup.py - http://markup.sourceforge.net/
HTML.py - http://www.decalage.info/en/python/html
Also, I feel that using a templating engine would be over-kill, but if you differ please say it and why.
Any other recommendation?
Maybe you could try Markdown instead, and convert it to HTML on the fly?
You don't necessarily need something complex - for instance, here's a ~150 line library to generate HTML in a functional manner:
http://github.com/Yelp/PushmasterApp/blob/master/pushmaster/taglib.py
(Full disclosure, I work with the person who originally wrote that version, and I also use it myself.)
Why would a templating engine necessarily be overkill? You don't need the whole web framework just to use the templating engine (at least, for most templating engines). Mako for example can be used stand-alone just fine, and I often use it to generate html files (reports from a db and such)
ElementTree can produce html with some limitations. I'd write it like this:
from xml.etree.ElementTree import ElementTree, Element, SubElement
import sys
html = Element('html')
head = SubElement(html, 'head')
style = SubElement(head, 'link')
style.attrib = {'rel': 'stylesheet', 'href': 'style.css', 'type': 'text/css'}
body = SubElement(html, 'body')
para = SubElement(body, 'p')
para.text = 'Lorem ipsum sit amet'
doc = ElementTree(html)
doc.write(sys.stdout)
In case of moderately complex html I'd stick with some templating engine: Jinja2, Mako, Cheetah, just to name a few.
If you have just some simple static HTML files. Then why not use string templates like so.
import string
TEMPLATE_FORMAT = """
<html>
<head><title>Trial</title></head>
<body>
<div class="myclass">$my_div_data</div>
</body>
"""
my_div_data = "some_data_to_display_in_HTML"
TEMPLATE = string.Template(TEMPLATE_FORMAT)
html_data = TEMPLATE.safe_substitute(my_div_data)
open("out.html", "w").write(html_data)
Give this a shot if you don't have too big HTML files to generate. Saves you on the learning you need to do if you decide to use libraries.
i recommend having a look at shpaml