We are using jinja2 to create our html but, because of the many loops and other things we do in jinja to produce the html, the html 'looks' ugly....(note: this is just for aesthetics). Is there anything we can do to clean up the html? (Other than the obvious of cleaning up our jinja2 code, which would make our template somewhat unreadable to us staffers)
Something like beautiful soup's prettify?
(Yes, I realize this question is a pretty nit-picky question...the ocd in me says to clean it up).
for instance:
<table>
<tbody>
<tr>
<td>
a column
</td>
<td>
a value
</td>
</tr>
</tbody>
</table>
Pretty ugly, eeh?
Add '-' to the tags:
{%- if 'this'=='this' -%}
{{ blah }}
{%- endif -%}
It looks like someone out there created a library to do just what need. See this library which I found attached to this question (whom you should upvote).
You can also configure Jinja to replace tags with nothing (instead of an empty line) by setting trim_blocks and lstrip_blocks to True. For example, in a Flask app, you might write:
app.jinja_env.trim_blocks = True
app.jinja_env.lstrip_blocks = True
The documentation explains whitespace control further.
Related
We have a website that is generated using Sphinx and reStructuredText. Albeit not ideal (I have inherited this code), it's something that so far has worked and serves the purpose. We're trying to extend it slightly and one request was to highlight better certain rows in a table based on a condition (just a bit of context).
What we noticed is that if the element that needs the style applied is the first one in the for-loop, the style gets instead applied to the parent (<tbody>) element.
This is the relevant piece of code that does not seem to be working as intended:
{% for codelist_item in codelist_json.data %}
{% if codelist_item.status == 'withdrawn' %}
.. rst-class:: withdrawn
* - {{codelist_item.code + " (withdrawn)"}}
{% else %}
* - {{codelist_item.code}}
{% endif %}
- {{codelist_item.name}}
...
{% endfor %}
NB: indentation is correct (as in it matches what's in our rst file)
Non working example: http://reference.iatistandard.org/202/codelists/BudgetIdentifierVocabulary/
whose HTML is:
<tbody class="withdrawn" valign="top">
<tr class="row-even">
<td>1 (withdrawn)</td>
<td>IATI</td>
<td>The budget identifier reported uses IATI budget identifier categories</td>
</tr>
Working example: http://reference.iatistandard.org/202/codelists/Currency/
<tr class="withdrawn row-even">
<td>BYR (withdrawn)</td>
<td>Belarussian Ruble</td>
<td>Withdrawn from ISO Currency codelist. Use code BYN.</td>
</tr>
While exploring the Sphinx docs, I stumbled across this bit that might be (or at least sounds) relevant
http://docutils.sourceforge.net/docs/ref/rst/directives.html#id12
This allows the "classification" of individual list items (except the first, as a preceding class directive applies to the list as a whole)
That seems to fit our problem, although like I said I'm not entirely sure it does relate to it.
So far, we tried checking {% forloop.first %}, moving the rst-class:: around, but nothing seems to work.
Any advice?
This is the data coming from my views.py:
gradebook_data = {
'G5A': [...],
'G5B': [...],
...
}
sections = [
('G5A': '5-Einstein'),
('G5B': '5-Bohr'),
...
]
In my template, I want to iterate the sections and display gradebook data inside a for loop like this...
{% for code, section in sections %}
<td>{{ gradebook_data.code }}</td>
{% endfor %}
This doesn't work since in Django it tries to do a dictionary lookup for gradebook_data['code'] when what I want to do is to get gradebook_data['G5A'].
Does anybody know a workaround or can point to my mistake? I have spent a whole day just for this already.
This was quite easy to do with PHP's Twig templating library.
If you're using the Django templating system you can register a custom filter, which has been documented several times on SO for exactly this purpose. For example, here.
I am using Markdown in an app to display a user biography. I want the user to be able to slightly format the biography, so I'm letting them use the TinyMCE editor.
Then, displaying it in the Django Template like this
{% load markup %}
<div id="biography">
{{ biography|markdown }}
</div>
The problem is, if there is a tag in the biography, it is not being escaped as django does everywhere else. This is the source output from a biography test:
<p><strong>asdfsdafsadf</strong></p>
<p><strong>sd<em>fdfdsfsd</em></strong><em>sdfsdfsdfdsf</em>sdfsdfsdf</p>
<p><strong>sdafasdfasdf</strong></p>
<script>document.location='http://test.com'</script>
How do I set Markdown to escape these malicious scripts?
According to django.contrib.markup.templatetags.markup.markdown's docstrings:
To enable safe mode, which strips raw HTML and only returns HTML
generated by actual Markdown syntax, pass "safe" as the first
extension in the list.
This should work:
{{ biography|markdown:"safe" }}
Markdown in safe mode would remove all html tags, which means your users cannot input HTML segments in the biography. In some cases, this is not preferable. I would recommend you use force_escape before markdown, so anything fed into markdown is safe.
For example, if your biography is <html>I'm really a HTML fan!</html>, using
{{ biography|markdown:"safe"}}
would produce HTML REMOVED.. Instead, if you use
{{ biography|force_escape|markdown }}
The output would be something like
<p><html>I'm really a HTML fan!</html></p>
Is there an easy way to use python string formatting from within a django template? That is, I'd like to be able to do something like this in a template
{{ variable|%.3f }}
I know in this case, one can just use
{{ variable|floatformat:3 }}
But I'd really like to be able to generically use any python string format on a django variable. In my system it's inconvenient to have to deal with two different ways to format output (python vs django), so I'd like to standardize. I could write a custom template tag like
{% pyformat variable format="%.3f" %}
or maybe a custom template filter like
{{ variable|pyformat:"%.3f" }}
Do either of these already exist? Will the customer filter work with a string passed in like that?
{{ variable|stringformat:".3f" }}
Source: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#stringformat
stringformat
I had omit the "%":
{{ variable|stringformat:".3f" }}
Hi all I am having some problems that I think can be attributed to xpath problems. I am using the html module from the lxml package to try and get at some data. I am providing the most simplified situation below, but keep in mind the html I am working with is much uglier.
<table>
<tr>
<td>
<table>
<tr><td></td></tr>
<tr><td>
<table>
<tr><td><u><b>Header1</b></u></td></tr>
<tr><td>Data</td></tr>
</table>
</td></tr>
</table>
</td></tr>
</table>
What I really want is the deeply nested table, because it has the header text "Header1".
I am trying like so:
from lxml import html
page = '...'
tree = html.fromstring(page)
print tree.xpath('//table[//*[contains(text(), "Header1")]]')
but that gives me all of the table elements. I just want the one table that contains this text. I understand what is going on but am having a hard time figuring out how to do this besides breaking out some nasty regex.
Any thoughts?
Use:
//td[text() = 'Header1']/ancestor::table[1]
Find the header you are interested in and then pull out its table.
//u[b = 'Header1']/ancestor::table[1]
or
//td[not(.//table) and .//b = 'Header1']/ancestor::table[1]
Note that // always starts at the document root (!). You can't do:
//table[//*[contains(text(), "Header1")]]
and expect the inner predicate (//*…) to magically start at the right context. Use .// to start at the context node. Even then, this:
//table[.//*[contains(text(), "Header1")]]
won't work since even the outermost table contains the text 'Header1' somewhere deep down, so the predicate evaluates to true for every table in your example. Use not() like I did to make sure no other tables are nested.
Also, don't test the condition on every node .//*, since it can't be true for every node to begin with. It's more efficient to be specific.
Perhaps this would work for you:
tree.xpath("//table[not(descendant::table)]/*[contains(., 'Header1')]")
The not(descendant::table) bit ensures that you're getting the innermost table.
table, = tree.xpath('//*[.="Header1"]/ancestor::table[1]')
//*[text()="Header1"] selects an element anywhere in a document with text Header1.
ancestor::table[1] selects the first ancestor of the element that is table.
Complete example
#!/usr/bin/env python
from lxml import html
page = """
<table>
<tr>
<td>
<table>
<tr><td></td></tr>
<tr><td>
<table>
<tr><td><u><b>Header1</b></u></td></tr>
<tr><td>Data</td></tr>
</table>
</td></tr>
</table>
</td></tr>
</table>
"""
tree = html.fromstring(page)
table, = tree.xpath('//*[.="Header1"]/ancestor::table[1]')
print html.tostring(table)