I would like to update template several times and then render it. From Jinja2 documentation, I have found that:
generate()
For very large templates it can be useful to not
render the whole template at once but evaluate each statement after
another and yield piece for piece. This method basically does exactly
that and returns a generator that yields one item after another as
unicode strings.
It accepts the same arguments as render().
This is my code and I don't know how to output/render template.
template_render.py
from jinja2 import Environment, Template, FileSystemLoader
file_loader = FileSystemLoader('templates')
env = Environment(loader=file_loader)
template = env.get_template('template_file.html')
template.generate(title='Lorem ipsum')
template.generate(subtitle='Dolor sit amet')
#How to render it now?
template_file.html
{{ title }} {{ subtitle }}
Related
I am trying to build a configuration generator for myself using jinja2. I need to know what are the expected variables and their keys before trying to render template to provide a sample file to fill before template rendering. Required parameters will change based on selected configuration type and used templates. I don't want to store all required parameters because templates will be changed time to time and also new templates will be added. There will be 50ish parameter per template
here is a sample template file
{{data.config1[0].field1}}
{{data.config2[0].field3}}
firt level change test
{% for row in data.config1 %}
{% if row.field3=='1' %}
something {{row.field1}} {{row.field2}}
{% else %}
something {{row.field1}}
{% endif %}
{% endfor %}
footer thingy
{{data.config2[0].field5}}
i tried to use find_undeclared_variables from jinja2.meta package
here is my sample code
import os
from jinja2 import Environment, FileSystemLoader,meta
template_filename = 'change.txt'
PATH = os.path.dirname(os.path.abspath(__file__))
TEMPLATE_ENVIRONMENT = Environment(
autoescape=False,
loader=FileSystemLoader(os.path.join(PATH)),
trim_blocks=False)
template_source =TEMPLATE_ENVIRONMENT.loader.get_source(TEMPLATE_ENVIRONMENT, template_filename)[0]
parsed_content = TEMPLATE_ENVIRONMENT.parse(template_source)
variables= meta.find_undeclared_variables(parsed_content)
print (variables)
this is what i can get
{'data'}
my desired output something like this.
{'config1':['field1','field2','field3'], 'config2':['field3','field5']}
please suggest.
I have used, Jinja2schema to generate expexted output.
There exists the
jinja2.meta.find_undeclared_variables function that may help you:
https://jinja.palletsprojects.com/en/3.1.x/api/#jinja2.meta.find_undeclared_variables
I am using django-summernote editor for creating posts with text and images which are saved in a character field as HTML tags.
I want to add a read-more functionality where a limited sized preview is shown for all the posts. An idea could be to truncate the character field, but it may lead to truncation of HTML image tags if they happen to be positioned between the boundary.
How to get around this?
Django has two template filters you can use to make sure your HTML doesn't get malformed: truncatechars_html and truncatewords_html
Template filters are just functions, so you can import them anywhere you need in your Python code and assign the result to a variable you can use elsewhere, etc.
Example:
from django.template.defaultfilters import truncatechars_html
html = """<p>Look, I’m some HTML. You can truncate me
with Django template filters</p>"""
truncated_value = truncatechars_html(html, 30)
I'm late to this party but this post came up in search results. I just got a working solution to this myself with a custom template filter. This allows you to drop in the break on a case by case basis like WordPress. Here is what I did (with help from this post and the Django docs):
Sample post submitted in a textfield:
<p>Here is some sample text</p>
<!--more-->
<img src="cool_photo.jpg" />
in templatetags/read_more.py
from django import template
from django.template.defaultfilters import stringfilter
register = template.Library()
#register.filter(name='read_more')
#stringfilter
def read_more(value):
pattern = "<!--more-->"
return value.split(pattern, 1)[0]
in the template that's rendering the truncated version:
{% load read_more %}
{{ object.body|read_more|safe }}
Since the split pattern is an html comment there's no need to cut it from the main post body template:
{{ object.body|safe }}
For example, I attached Jinja2 to my pythonic project with the next code (Jinja2 docs):
from jinja2 import Template
template = Template(text_of_the_template)
template.render(**kwargs)
The example of using a custom template tag (from here):
from jinja2 import contextfunction
#contextfunction
def widget(context, template_name, **extra_context):
t = jinja_env.get_template('widgets/' + template_name)
ctx = dict(context.items())
ctx.update(extra_context)
return t.render(ctx)
jinja_env.globals['widget'] = widget
# And then in the template:
{{ widget('last_tweets.html') }}
How to bind Jinja2 environment and the code above (the Template class)?
Instead of using jinja2.Template() to get your template you should get it through the environment.
So you will get something like this instead:
template = jinja_env.from_string(text_of_the_template)
template.render(**kwargs)
Here's the dos: http://jinja.pocoo.org/docs/api/#jinja2.Environment.from_string
I try to enable the trans tag and I've made a test template i18n.html:
{% trans %}For sale{% endtrans %}--{{message}}--{{decimal_format}}
Here is my python code according to the manpages:
from webapp2_extras import i18n as multilingua
import jinja2
from webapp2_extras.i18n import lazy_gettext as gettext
from webapp2_extras.i18n import lazy_gettext as _
from jinja2 import Environment, FileSystemLoader
jinja_environment = jinja2.Environment(loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
extensions=['jinja2.ext.i18n'])
# The code below seems wrong since it is django but it was the only way I could make the page load
jinja_environment.install_gettext_translations(django.utils.translation)
class HelloWorldHandler(webapp2.RequestHandler):
def get(self):
# Set the requested locale.
locale = self.request.GET.get('locale', 'pt')
multilingua.get_i18n().set_locale(locale)
message = multilingua.gettext('For sale')
#django.utils.translation.activate('pt')
template = jinja_environment.get_template('templates/i18n.html')
decimal_format = multilingua.I18n(self.request).format_decimal(1000)
self.response.out.write(template.render(message=message, decimal_format=decimal_format))
I could not make it work without django and therefore I ask how to lose the django translation and staying with webapp2.i18n + jinja instead.
There was also a discussion in a thread where I'm not the only one saying that documentation is somewhat incomplete or hard to find. Could you please answer or comment which is the recommended way of making the trans tag work and why I must include jinja_environment.install_gettext_translations(django.utils.translation)
?
When I try to remove my use of django I also lose the functions of webapp2.i18n. My locale files are both in locale/... and conf/locale.. since the first is the default for webapp2 and the second is the default for django translations, so I could really use some guidelines for best practice here to get rid of the django dependecies and use webapp2 and jinja for rendering my localizations.
If to any help, I did receive an error message when trying to remove django:
self.response.out.write(template.render(message=message, decimal_format=decimal_format))
File "/media/Lexar/montao/montaoproject/jinja2/environment.py", line 894, in render
return self.environment.handle_exception(exc_info, True)
File "/media/Lexar/montao/montaoproject/templates/i18n.html", line 2, in top-level template code
{{ _('For sale') }}--{{message}}--{{decimal_format}}
UndefinedError: 'gettext' is undefined
Thank you
Take a look at Jinja2's i18n Extension documentation. Calling install_gettext_translations basically sets the object through which Jinja2 will call gettext, ngettext, etc, in order to translate strings when it encounters a {% trans %} tag.
Since those functions are defined on webapp2.i18n (see here), jinja2 will successfully call those functions to retrieve translations, dependent upon your call to set_locale inside of the request. I don't have the code in front of me, but I'd guess that gettext and company defined in webapp2.i18n are merely proxies to call webapp.i18.get_i18n().gettext, which is the magic that makes all of this work.
Here is a working example for Django+jinja2:
from jinja2 import PackageLoader, Environment
from django.utils import translation
...
jinja_environment = Environment(loader=PackageLoader('website', 'templates'),
extensions=['jinja2.ext.i18n'])
jinja_environment.install_gettext_translations(translation)
template = jinja_environment.get_template('test.jinja.html')
page_next_app_table = template.render()
...
In test.jinja.html:
<html>
<b> {{ _( "Traslate This" ) }}:</b>
</html>
In one of my Django templates, I have a chunk of HTML which repeats at several places in the page. Is there a way I could use another template for this chunk alone and "instantiate" the template where required?
You need to read about template inheritance.
Or you can use template composition.
Inheritance is, generally, a better way to go.
I've met the same issue some time ago and here is what I got.
Seems like it's not really well documented, but there is quite obvious solution - insert HTML blocks in your main template and then pass the result of the other template render there.
Example:
In main template (app/main.html):
<!-- ... -->
{% autoescape on %}
{{html}}
{% autoescape off %}
<!-- ... -->
In view code:
from django.template.loader import get_template
def my_view(request, ...):
# Do stuff...
context = {'data': 'data'}
t = get_template('app/partial_template.html')
html = t.render(context=context)
return render(request, 'app/main.html', context={'html': html, 'rest_data': 123})
Thus you'll get some template rendered inside another template with perfect separation of concerns (parent template doesn't know anything about child's context nor about child itself).