-
Notifications
You must be signed in to change notification settings - Fork 33
Genshi to Jinja conversion
<html xmlns:py="http://genshi.edgewall.org/"
xmlns:i18n="http://genshi.edgewall.org/i18n"
xmlns:xi="http://www.w3.org/2001/XInclude"
py:strip="">
...
</html>
-> replace with
{% extends "page.html" %}
<py:def function="page_title">New - Harvest Source</py:def>
-> becomes
{% block title %}New - Harvest Source - {{ super() }}{% endblock %}
<py:def function="page_heading">New harvest source </py:def>
-> becomes
<h1>New harvest source</h1>
<py:def function="body_class">no-sidebar</py:def>
-> delete
<py:def function="sidebar">
-> moves to
{% block secondary_content %}
<py:def function="optional_head">
...
</py:def>
e.g. links to CSS -> becomes
{% block optional_head %}
...
{% endblock %}
<py:match path="breadcrumbs">
<li><a href="/data/search">Datasets</a></li>
<li><a href="/harvest">Harvest sources</a></li>
<li><a href="/harvest/new">New source</a></li>
</py:match>
becomes
{% block breadcrumb_content %}
{{ h.build_nav('dgu_search', _('Datasets')) }}
{{ h.build_nav('harvest', _('Harvest sources')) }}
{{ h.build_nav('harvest_new', _('New source')) }}
{% endblock %}
NB The first param is the route 'name' - you probably need to add it as a new param at the start of the route definition in plugin.py e.g.
map.connect('/harvest/new', controller=controller, action='new')
becomes
map.connect('harvest_new', '/harvest/new', controller=controller, action='new')
<div py:match="content">
...
</div>
-> becomes
{% block primary_content_inner %}
...
{% endblock %}
In some cases py:def will be replaced with a block name (see breadcrumbs, title) but in others they'll actually be macros (see _dgu_jinja_util.html). The common form for macros is :
{% macro name(arg1, arg2) %}
{% endmacro %}
When you want to use the macro elsewhere you should use it as
{% import "_dgu_jinja_util.html" as m with context %}
{{ m.mymacro() }}
<xi:include href="../layout.html" />
Delete this reference, but check the file it refers to. If it doesn't exist then it will fallback to ckan/templates/layout.html which has nothing in, so you can ignore it.
${...}
-> becomes
{{ ... }}
I suggest we do put in a space just inside each bracket, for easy reading.
Typically in genshi there was a lot of
<py:if="errors.get('field')">
<div>....
</py:if>
we should change to using the macros display_error
in _dgu_jinja_util.html instead. It is used as
{{ display_error(errors, name, field_error=False, msg=None) }}
errors
is the usual error dict, and name is the name of the field. If it isn't present the macro does nothing. If it is present it will show an error message using:
- msg if not None
- the contents of the error dict
The field_error is used for cases where the errors were previously displayed as a p class="field-error"
and the default is to show a normal bootstrap alert.
${c.user}
- A couple of context variables can still be used: c.user, c.user_obj
- Most you should pass in from the controller using extra_vars:
render('source/new.html', extra_vars={'data': data})
and then you can use them in the template unqualified:
{{data}}
You can't use dict(), or int() in the template. There are helpers for some h.as_dict()
, and for things like bool() you should check if val
. You also can't do something like
if type(x) is dict
instead do
if h.is_dict(x)
${g.site_url}
Some are defined? e.g. g.tracking_enabled Others need passing in using extra_vars
{{ h.url_for(...) }}
These should all still work - both ckan and DGU helpers.
Controller:
c.form = render('source/new_source_form.html', extra_vars=vars)
Template:
${h.literal(c.form)}
Consider calling the snippet from the template, rather than rendering it separately and passing in the HTML.
{% snippet 'snippets/new_form.html' %}
<py:for>
{% for item in navigation %} .. {% endfor %}
<py:if>
{% if group.description %} .. {% else %} .. {% endif %}
{% if group.description %} .. {% elif group.name %} ... {% else %} ... {% endif %}
Sometimes you need to set a var to save calling a function too frequently. You can do this like
{% set myvar = h.slow_function() %}
You need to be careful though, as inside a forloop this can leak out and may not be set on each iteration. In these cases you should do:
{% for x in loop_var %}
{% with %}
{% set var = h.myfunction() %}
{% endwith %}
{% endfor %}
You could set the var in the with block, but perhaps it is more legible to structure it as above.
Helper templates (such as _dgu_util.html) are problematic because they are used in several places. Instead use _dgu_jinja_util.html until all the necessary templates have been replaced.
The following snippet has been removed from _dgu_jinja_util.html as it caused recursion problems, and so you will need to include it in your page (such as inventory/read.html)
{% block optional_head %}
<link rel="alternate" type="application/rdf+xml" href="{{h.url_for(controller='package', action='read', id=c.pkg.name, format='rdf')}}"/>
<script type="text/javascript" src="{{h.url_for_static('/scripts/dgu-package.min.js')}}"></script>
<script type="text/javascript">
window.DATASET_ID = "{{c.pkg_dict.get('id')}}";
</script>
{{ super() }}
{% endblock %}
The extra "!" tells Genshi not to leave it in the rendered HTML.
<!--! Comment -->
-> replace with
{# Comment #}
But you can leave rendered comments:
<!-- Comment -->