How do I build reusable widgets in jinja2? - python

I want to define a widget something vaguely like this:
{% block css %}
.mywidget {
css: goes_here;
{% endblock %}
{% block widget %}
<div class="mywidget">
<!-- structure goes here -->
</div>
{% endblock %}
{% block script %}
$( ".mywidget" ).addFunctionality(stuff)
{% endblock %}
In other words, a deceleration of what CSS the widget needs, what its contents are (preferably parametrized in some way), and what scripts it requires at the end of the file. Then, I would like to be able to extend a layout template, add widgets to the body (possibly multiple widgets of the same type with different parameters of some kind), and have the CSS and javascript properly added to the top and bottom of the layout template, once per widget type.
This seems like a pretty clean and straightforward design, and coming from a native UI design perspective, I am confused as to why I cannot find any examples of how to do something like this.

You have fleshed out part of the design for a widget system, but really have only shown how you would go about designing the widget. The other part is how you would end up USING the widget in Jinja.
For example, you could use Jinja Macros to define the widget. Create a file "mywidget.html" and use...
{% macro css() -%}
.mywidget {
css: goes_here;
}
{% endmacro %}
{% macro widget() -%}
<div class="mywidget">
<!-- structure goes here -->
</div>
{% endmacro %}
{% macro script() -%}
$( ".mywidget" ).addFunctionality(stuff)
{% endmacro %}
Then, in your HTML using this widget, you could do...
{% import 'mywidget.html' as mywidget %}
...
<html>
<head>
<style>
{{ mywidget.css() }}
</style>
<head>
<body>
{{ mywidget.body() }}
<script>
{{ mywidget.script() }}
</script>
</body>
</html>
Of course, the problem here is that you need to manually put all of the widgets into the various areas. Once you get a larger number of widgets, it might be hard to keep track of them, and it would be easy to, for example, have the mywidget.script() code created multiple times, which would cause duplicate event fires.
And, of course, you could always have Python objects as part of the context rendering the final solution. The important thing to note is that Jinja just renders text from templates. The templates don't even have to be HTML template, you could use Jinja to render a plain text e-mail. Therefore, it would be difficult to imagine the authors of the library trying to create these sort of "widget" system and expect everyone to be happy by the result. Why increase the complexity of the library with such a complex feature that they will need to support (especially since Jinja provides people with the tools to build such a framework already)?

Related

How to avoid rendering a block in a base template - or: how to define a multiline block-like variable?

I am rather new to jinja, so please excuse this potentially dumb question ...
I have a jinja macro sitting in a file named lib.jinja which looks as as follows
{% macro some_macro(some_content) %}
<div class="some_class">{{ some_content }}</div>
{%- endmacro %}
I import it from another file named content.htm, which looks roughly as follows:
{% from "lib.jinja" import some_macro %}
{% block content %}
Some content
{% endblock %}
{{ some_macro(self.some_macro(self.content())) }}
The rendered output looks as follows:
Some content
<div class="some_class">Some content</div>
Notice that the content appears twice, once rendered through/by the macro, another time - directly above - rendered like it was defined in the block named content in content.htm. I would love to avoid that the block is rendered twice - it is supposed to be fed into the macro and rendered through it only.
I appears that I can "work around" it by turning content.htm into a child template (by adding an extends tag at its top) of an empty base template.
Maybe I have a lack of understanding for the concepts here: A block is not a variable - I get that. If there is no extends tag, the template is treated as a base template, I assume. If there are no child templates or other directives, I guess the block is just rendered as-is and then, for a second time so to speak, picked up by the macro - correct?
How can I solve this in a sane manner, i.e. how could I handle this other than by extending an empty base template? Is there another type of block or variable that would fit my needs?
Just after I submitted this question, I finally found what I was looking for in the manual: Block Assignments.
{% from "lib.jinja" import some_macro %}
{% set content %}
Some content
{% endset %}
{{ some_macro(self.some_macro(content)) }}
The set and endset tags solve my problem.

using angular expressions in a django based webapp

I recently started with django and I have experience with angularJS. I got pretty confused by the static media rendering of Django which uses the same moustache ({{ }}) as angular. So how to use angular expressions while working with django..
<body>
<h1>Including Static Media</h1>
<img src="{% static "rango.jpg" %}" alt="Picture of Rango" /> <!-- Images -->
</body>
Instead of using the rendering as it is, can i use something like
image src="/static/images/xyz.jpg"
However if I want to load my images or js script dynamically or if I have to make URL's dynamically using something like ng-href="#!/{{redirectService(parameters)}}". It seems that syntax of both frameworks conflict alot. Can anyone help me regarding this.?
Check out the {% verbatim %} tag and/or the {% templatetag %} tag.
From the docs:
verbatim
Stops the template engine from rendering the contents of this block
tag.
A common use is to allow a JavaScript template layer that collides
with Django’s syntax. For example:
{% verbatim %}
{{if dying}}Still alive.{{/if}}
{% endverbatim %}
You can also designate a specific closing tag, allowing the use of {% endverbatim %} as part of the unrendered contents:
{% verbatim myblock %}
Avoid template rendering via the {% verbatim %}{% end verbatim %} block.
{% endverbatim myblock %}
templatetag
Outputs one of the syntax characters used to compose template tags.
Since the template system has no concept of “escaping”, to display one
of the bits used in template tags, you must use the {% templatetag %}
tag.
The argument tells which template bit to output:
Argument | Outputs
————————————————|————————
openblock | {%
closeblock | %}
openvariable | {{
closevariable | }}
openbrace | {
closebrace | }
opencomment | {#
closecomment | #}
Sample usage:
{% templatetag openblock %} url 'entry_list' {% templatetag closeblock %}

jinja2: Can I render template tags from an expression?

How would I return text with template markup from an expression and have the tags rendered by Jinja? It looks like Jinja only makes one pass, and just escapes and dumps the text in without further processing it as part of the template (which would be the right thing 99% of the time). Is there a way to make two passes with the renderer, or render the result of my expression first and pass it to the template?
Simplified Problem
I have included further details below in case there is more to this than I think, but this should be all the information needed for the problem.
If do_render() returns <p>Hello there {{ current_user.name }}</p>, how could I do the following in a template, so that I obtain the value of name?
<div>
{{ do_render() }}
</div>
This renders as <div><p>Hello there {{ current_user.name }}</p></div>, when I want <div><p>Hello there Sam</p></div>.
Complete Problem
I'm using Flask, Flask-Bootstrap, and Flask-Nav with Python 2.7. I could just create the navigation bar myself and none of this would matter, but "autogenerated" sounded so much simpler...
Flask-Bootstrap provides a Flask-Nav compatible renderer; I have subclassed it to modify my navigation bar. I'm trying to add a logon form in the navigation bar, right-aligned. Because the BootstrapRenderer generates the complete navbar, I have to inject my form into it prior to the closing tags (alternatively, I could skip super() and do it all myself).
class MyRenderer(BootstrapRenderer):
def visit_Navbar(self, node):
""" Returns the html for a Bootstrap navigation bar. """
root = super(MyRenderer, self).visit_Navbar(node)
# Replace the navbar style with my custom css
root['class'] = 'navbar navbar-mystyle'
# Here I try injecting a login form. This is the correct position,
# and it inserts properly; it just treats {{, }}, {%, %}
# as nothing special.
elem = root[0][1] # div class="navbar navbar-collapse"
elem.add(
dominate.util.include(
os.path.join(
config.app_path_root, app.template_folder, 'inc/login_form.jinja')))
# I have also tried
# elem.add('{% block nav_right %}{% endblock %}')
# thinking I would use inheritance later (still my preference).
return root
I then register the renderer with Flask-Nav, and render it by inserting {{ nav.main_nav.render() }} into my base template, which my .html files inherit from. All of this works.
My problem is that I only want the login form when the person is not logged in.
The login_form is:
{% if not current_user.is_authenticated() %}
<form class="navbar-form navbar-right" role="search" action="login" method="post">
<div class="form-group"><input type="text" name="username" /></div>
<div class="form-group"><input type="password" name="password" /></div>
</form>
{% else %}
<div class="navbar-right">
Welcome {{ current_user.name }} | Logout
</div>
{% endif %}
My HTML output is identical to the template; neither statements, expressions, nor comments are treated as such.
Other attempts: I have generated the navbar first, then passed it to the template via render_template('index.html', navbar=navbar) but I have the same problem. I have also tried macros. I'm about ready to write my navigation menu in the base template myself and be done with it, but now it feels like that would be giving up.
Other than {% include ... %} and {% extends ... %}, you're not going to be able to have the template system automatically render something that's added to a template during runtime without a bit of customization.
The beautiful part about Jinja 2 is that its API is very powerful and you can do many things without having to feel like your "hacking" the system. To do what your first example is implying, you just need to have the function render the included template snippet snd return a rendered string. If you're expecting the template to be rendered with the context of the parent template, that's not gonna happen automatically, but that's not a problem since you can pass in whatever you need directly in your function call in the template.

django cms: template for placeholder

Placeholder : packages_details_header
Banner
static block (where we add the text in textarea and convert it into html at time of render)
two label
label for heading
But as per the html wrappers and css classes, I think it is difficult to implement above structure
So my suggestion is
can we have pre defined template for placeholder?
Where all above listed plugins are predefined in placeholder template, like as shown in following example
{% block content %}
{% placeholder "packagesdetailscontent" %}
<div class=”banner”> banner plugin </div>
<div class=”static”> Static plugin </div>
..
..
..
<h2> label plugin</h2>
{% endplaceholder "packagesdetailscontent" %}
{% endblock content %}`
Please let me know, if there is any solution on it
thanks,
B
You can limit plugins allowed in a placeholder using CMS_PLACEHOLDER_CONF
See http://django-cms.readthedocs.org/en/latest/reference/configuration.html#cms-placeholder-conf
Update:
I read your question again, if I understand it correctly.. you are struggling with wrapping plugin with html class?
Have you had a look at https://github.com/divio/djangocms-style
It would allow you wrap your existing plugin in whatever classes you need :-)

In Jinja2, how can I use macros in combination with block tags?

I'm a front end developer, and I've been trying to get a hang on using Jinja2 effectively. I want to tweak a current site so it has multiple base templates using inheritance, it fully uses block tags to substitute content and override it, and uses macros to support passing of arguments.
My base template contains this code (edited for simplicity):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
{% from "foo.html" import macro1, macro2, macro3 %}
{% macro base_template(title=none, arg2=none, urls={}, arg3=false) %}
<html>
<title>{{ title }} | Site.com</title>
....
{{ caller() }}
....
</html>
{% endmacro %}
{% block content %}{% endblock %}
And my pages that extend it look like this:
{% extends "base.html" %}
{% block content %}
{% call base_template(title="home", arg2="active", arg3="true") %}
(html code here)
{% endcall %}
{% endblock %}
So basically all the pages extend base, they call a macro and pass arguments to that macro. I don't quite understand it all, but the main point is that this allows default values and a degree of flexibility that doesn't require redefining an entire block: it gives some degree of flexibility and power. Again this is heavily simplified.
The only problem is, this negates my ability to use blocks. Macros are for flexibility, but with blocks, I have the ability to override something entirely, or use it's parents contents and add to it, which I can't do with Macros (at least I don't think). The problem is, I can't wrap things in blocks, else they won't see the values in the macro. For instance, doing this:
{% block title %}<title>{{ title }} | Site.com</title>{% endblock %}
Will fail because it will say title is undefined.
Ultimately I am looking for a way to utilize both the power and organiztional aspects of blocks, but still be able to utilize the logic & terseness of macros. If anyone could give me any help as to how I might go about this problem, I would really appreciate it.
Blocks are only definable at a template's top level. If you extend a template, any values set in the child template using a set tag will be accessible from the template it is extending. For example, if you have a template named layout.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<title>{{ title }} | Site.com</title>
....
{% block content %}{% endblock content %}
....
</html>
And you have this child template, index.html:
{% extends "layout.html" %}
{% set title = 'Homepage' %}
{% block content %}
(html code here)
{% endblock content %}
Then the reference to title in the parent would resolve to 'Homepage'. You can do this with any type of variable. For what you're doing, I don't think there is any need for macros - if you take advantage of this feature and place blocks well, you will be able to do pretty much everything you need to do as far as layouts are concerned. I would look at some of the templates used by Plurk Solace, which is written by one of the Jinja2 authors, if you want to get a good idea of when to use various features of Jinja2.

Categories