I am trying to make my templating engine for Python work backwards. That is, not only generate a document given a template and data, but also extract the data given a template and a document.
Given the page
<ul>
<li>What is your name, stranger?</li>
</ul>
and the template
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li>{{ question.text }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
it will return a latest_question_list containing that one item.
What tool do you use to do this? It does not have to support Django templates, other templating engines will do just fine.
This breakthrough happened already. This is called bidirectional or invertible parsing. See it discussed here https://news.ycombinator.com/item?id=16392654
And this paper https://dl.acm.org/doi/10.1145/1863523.1863525 "Invertible syntax descriptions: unifying parsing and pretty printing"
And this Haskell library https://hackage.haskell.org/package/roundtrip among others
source: https://news.ycombinator.com/item?id=25319810
Related
I have recently started to learn Django, so I came across with some HTML templates, but those are pretty unfamiliar for me, they mostly consist of {% and {{
For example:
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
Vote again?
What are they? Implementations from other languages or HTML syntax? I'd be happy to get some docs, websites or examples too.
The {% _________ %} are template tags. They are used to interpolate a tag into the space. Examples include extend, include, and load to name but a few. They often extend, insert, or give some sort logical functionality in some way (if conditions or loops, etc).
The {{ ___________ }} syntax is for template variables. This is used to interpolate a variable declared either as one of the built-in options or your own which you have created from any number of methods (models, view context, etc).
The Django docs are pretty thorough with use cases of all these. Another website which shortlists these to make them readily understandable is https://www.djangotemplatetagsandfilters.com/
It doesn't mean anything in html itself, it means something in Django template language. For example:
{{ choice.choice_text }}
will substitute value of that variable during template rendering.
The other one {% and %} is used for template processing, for example to indicate to template processor that some task needs to be completed. Good example is:
{% if error %}
{{ error }}
{% endif %}
That means that the variable error will be displayed (rendered) only if it exists, or to be more precise if it has some value.
The ones you are referring are jinja codes. They are very essential to work with Django and also they easy to understand when you have general understanding about python and django. You can find the documentation about jinga in this URL Jinja2 Documentation
So I am new to Django (and complete the 7 part tutorial) as well as read the flatpages app documentation.
At the end of which, whoever wrote the Django documentation gives a demonstration as to how one would retrieve all the flatpages:
{% load flatpages %}
{% get_flatpages as flatpages %}
<ul>
{% for page in flatpages %}
<li>{{ page.title }}</li>
{% endfor %}
</ul>
I now have flatpages working (e.g. if I go to /pages/my_flatpage/ the default template I have renders. as I have included url(r'^pages/', include('django.contrib.flatpages.urls')) in the urlpatterns.
So I am now in another app of mine and want to link to these flatpages. Using the code above I create the links. However, when I click on them, they do not render as they are routed to /my_flatpage/ rather than /pages/my_flatpage/.
So I tried including the url pattern in my app, but that didnt work. How can I get the to go to the right place?
Since you're not hosting the pages directly at the root, the url attribute doesn't return the whole path. Instead you should use the URL reversing functionality as with any other object:
{% for page in flatpages %}
<li>{{ page.title }}</li>
{% endfor %}
In jinja I can create macros and call it in my template like this:
{% macro create_list(some_list) %}
<ul>
{% for item in some_list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endmacro %}
HTML code....
{{ create_list(list1) }}
{{ create_list(list2) }}
{{ create_list(list3) }}
I read in django docs that django templates hasn't macro tag. I'm interested in the best way to do something like this in django templates.
As you already said macros don't exist in django's templating languages.
There are template tags to do more difficult things in templates, but that's not what you're looking for either, because django's templating system also doesn't allow parameters being passed to functions.
The best thing for your example would be to use the include tag:
https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#include
Here's how I would use it:
templates/snippets/list.html
<ul>
{% for item in list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
templates/index.html
{% include 'snippets/list.html' with list=list1 %}
{% include 'snippets/list.html' with list=list2 %}
{% include 'snippets/list.html' with list=list3 %}
...
I found two packages to offer that:
https://github.com/twidi/django-templates-macros
https://github.com/nalourie/django-macros
they both look to work the same: install with pip, put in INSTALLED_APPS, {% load macros %} in the template, write and use them.
template/partials/example-partial.html
{%if partial_name == 'partial1'%}
<ul>
{% for item in list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{%endif%}
{%if partial_name == 'partial2'%}
<ul>
{% for item in list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{%endif%}
{%if partial_name == 'partial3'%}
<ul>
{% for item in list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{%endif%}
templates/index.html
{% include 'partials/example-partial.html' with list=list1 partial_name="partial1"%}
{% include 'partials/example-partial.html' with list=list2 partial_name="partial2"%}
{% include 'partials/example-partial.html' with list=list3 partial_name="partial3"%}
... just start using jinja with Django.
it's very easy to turn it on
and you can use both template engines at the same time, of course for different files.
In the Django Template Language macros are not supported, but you can select the Jinja engine in order to use macros. Keep in mind that if you are building a plugable application, Django recommends using the DTL.
A Django project can be configured with one or several template
engines (or even zero if you don’t use templates). Django ships
built-in backends for its own template system, creatively called the
Django template language (DTL), and for the popular alternative
Jinja2.
The Django template language is Django’s own template system. Until
Django 1.8 it was the only built-in option available. It’s a good
template library even though it’s fairly opinionated and sports a few
idiosyncrasies. If you don’t have a pressing reason to choose another
backend, you should use the DTL, especially if you’re writing a
pluggable application and you intend to distribute templates. Django’s
contrib apps that include templates, like django.contrib.admin, use
the DTL.
Here is the link to the documentation for configuring other template engines: https://docs.djangoproject.com/en/dev/topics/templates/#configuration
I loaded a custom template tag note_extras.py in base.html.
base.html
<div id="wrap">
{% load note_extras %}
{% block content %}
{% endblock %}
</div><!--wrap-->
but it is not accessible at templates which is an extend of base.html ie::
home.html
{% extends "base.html" %}
{% block content %}
<div class="container">
{% create_tagmenu request.user.pk %}
</div>
{% endblock %}
it is working fine if i load note_extras in home.html ie:
{% extends "base.html" %}
{% load note_extras %}
....
In Django template language, you must load all needed template libraries in each of the templates.
I personally think it is a good idea because it makes templates more explicit (which is better than implicit). Ill give an example. Prior to Django 1.5, the default behavior for a url tag was to provide the view name in plaintext as well as all the needed parameters:
{% url path.to.view ... %}
There however was no way to provide the path to the view via a context variable:
{% with var='path.to.view' %}
{% url var ... %}
{% endwith %}
To solve that, starting with 1.3, you could import the future version of the url tag (which became the default in 1.5) by doing:
{% load url from future %}
{% url var ... %}
or
{% url 'path.to.view' ... %}
Now imagine that you would need to create a template which would extend from a base template which you did not create (e.g. one of django admin base templates). Then imagine that within the base template it would have {% load url from future %}. As a result, {% url path.to.view ... %} within your template would become invalid without any explicit explanation.
Of course this example does not matter anymore (starting with 1.5) however hopefully it illustrates a point that being explicit in templates is better than implicit which is why the currently implementation is the way it is.
If you want that a template tag is loaded in every template you want to do it in the init file of your app:
from django.template.loader import add_to_builtins
add_to_builtins('my_app.templatetags.note_extras')
In case anyone was wondering, add_to_builtins has been deprecated but one could still load a tag for all of the templates in the project via settings.TEMPLATES - supported for Django 1.9 onwards as described here:
https://stackoverflow.com/a/59719364/2447803
I have created a templatetag that loads a yaml document into a python list. In my template I have {% get_content_set %}, this dumps the raw list data. What I want to be able to do is something like
{% for items in get_content_list %}
<h2>{{items.title}}</h2>
{% endfor %}`
If the list is in a python variable X, then add it to the template context context['X'] = X and then you can do
{% for items in X %}
{{ items.title }}
{% endfor %}
A template tag is designed to render output, so won't provide an iterable list for you to use. But you don't need that as the normal context + for loop are fine.
Since writing complex templatetags is not an easy task (well documented though) i would take {% with %} tag source and adapt it for my needs, so it looks like
{% get_content_list as content %
{% for items in content %}
<h2>{{items.title}}</h2>
{% endfor %}`