Tag or inherit the same code in Django template with minor changes - django

I have a bunch of code that I will need to use repeatedly on a page, and on multiple pages. For example, here is a shorter version of the code:
<a href="#"
data-toggle="popover"
title="{% for terms in s_terms %}{% if terms.slug == 'neuron' %}{{terms.title}}{% endif %}{% endfor %}"
data-content="{% for terms in s_terms %}{% if terms.slug == 'neuron' %}{{terms.para_one}}{% endif %}{% endfor %}">
Toggle popover
</a>
There is a lot more code in the block. Now, for obvious reasons I do not want to keep repeating such large chunks of code. I am a fan of the DRY approach.
However, I can't figure out how to render this same piece of code repeatedly. The only thing that would change is the word = "neuron" in there. I thought of using template tags, but that didn't work.
I tried saving the code as a separate file, and inherit it within my template, but then I can't change the keyword ('neuron'). I also tried creating a separate dynamic page, and include that in my Django template, but looks like the include tag only works for templates, and not for dynamic pages.
Can anyone help, please? Thank you, in advance.

You could use Django template built-in template tag include.
From the documentation:
Loads a template and renders it with the current context. This is a
way of “including” other templates within a template.
So, you can just extract your snippet in a separate template and then use it with:
{% include "snippet_template.html" %}
Additionally, you can pass a variable to the include template using the with keyword - you would use this to pass your word parameter:
{% include "snippet_template.html" with word="neuron" %}

As #bonidjukic wrote the include statement is what you search.
But include statement inside for-loop could reach one weakness of Django template Engine (vs Jinja). You include just variables, so it will be fast.
In the case of needing tags (like trans), Django will load tags at each include. Where Jinja will have global "tags".
So just be careful, with how you DRY you templates.

Related

How to assign value to a variable on Django template through jQuery

I have a Django template file working with a passed value like the below.
{% include 'boutique/rating.html' with score=[I want to put value here] %}
When I usually put value into the template, I could easily do it by doing like the below.
{% for store in stores %}
{% include 'boutique/rating.html' with score=store.review_score %}
{% endfor %}
However, as I get into more complex templates, I need to assign the value to the score parameter in the include section through jQuery. Is there a way that I can acheive this through jQuery?
What you need to understand is this: The part of the template between {% and %} is interpreted by Django. It is processed entirely on the server. In other words, it never shows up in the browser, but gets replaced by some sort of standard HTML.
On the other hand, jQuery is a Javascript library and operates entirely in the browser -- it doesn't know anything about the server or Django.
So, to modify the included template with jQuery, you have to find out what HTML it renders to. You can probably do that by looking at the included template file. Then, treat that HTML the way you would any other part of the page for manipulation with jQuery.

Does django support separating your templates into parts?

I would like to create separate templates for each part of the page like Navigation, Side bar, Login panel, etc. Django seems to use inheritance rather than composition. I was wondering if there is any support for separating templates out into parts and passing in template specific models to each template. I'm thinking of something like:
values = {
'navbar_data' = ...
'sidebar_data' = ...
}
{{ template.render('navbar', navbar_data) }}
{{ template.render('sidebar', sidebar_data) }}
There are many good ways to do this.
You can use the builtin templatetage include for this. This template tag allows you to to use and reuse specific fragments of a template. This is usually most useful for mini templates that say represent a single model and will be used throughout the site. This can be especially useful if you combine it with the with templatetag to allow you to craft the context used in the included template
Alternatively just simply using block may give you the feel you're looking for
Finally you can use custom inclusion templatetags (https://docs.djangoproject.com/en/1.4/howto/custom-template-tags/#inclusion-tags) to give you an even deeper level of control. These will allow you to render a subtemplate with a completely custom context.
That is what templatetags are for. You define a tag in a file called myapp/templatetags/mytags.py, then in your template do this
{% load mytags %}
{% navbar %} {% sidebar %}
The official documentation has plenty of information about this.

Django conditional template inheritance

I have template that displays object elements with hyperlinks to other parts of my site. I have another function that displays past versions of the same object. In this display, I don't want the hyperlinks.
I'm under the assumption that I can't dynamically switch off the hyperlinks, so I've included both versions in the same template. I use an if statement to either display the hyperlinked version or the plain text version. I prefer to keep them in the same template because if I need to change the format of one, it will be easy to apply it to the other right there.
The template extends framework.html. Framework has a breadcrumb system and it extends base.html. Base has a simple top menu system.
So here's my dilemma. When viewing the standard hyperlink data, I want to see the top menu and the breadcrumbs. But when viewing the past version plain text data, I only want the data, no menu, no breadcrumbs. I'm unsure if this is possible given my current design. I tried having framework inherit the primary template so that I could choose to call either framework (and display the breadcrumbs), or the template itself, thus skipping the breadcrumbs, but I want framework.html available for other templates as well. If framework.html extends a specific template, I lose the ability to display it in other templates.
I tried writing an if statement that would display a the top_menu block and the nav_menu block from base.html and framework.html respectively. This would overwrite their blocks and allow me to turn off those elements conditional on the if. Unfortunately, it doesn't appear to be conditional; if the block elements are in the template at all, surrounded by an if or not, I lose the menus.
I thought about using {% include %} to pick up the breadcrumbs and a split out top menu. In that case though, I'll have to include it all the time. No more inheritance. Is this the best option given my requirement?
You can put your hyperlinks inside a block that is overridden by the loading templates.
Let's say you have your framework.html like this:
{% extends "base.html" %}
<html>...<body>...
{% block hyperlinks %}
your hyperlinks here
{% endblock %}
rest of the code
</body></html>
You can then create something of a nolinks.html template and use it
{% extends "framework.html" %}
{# here you'll have everything from framework
but now we disable the breadcrumbs #}
{% block hyperlinks %}{% endblock %}
If you're getting the past data you can then use nolinks to render instead of framework.
I hope this helps.
From here: Any way to make {% extends '...' %} conditional? - Django
It can be done like this :
{% extends ajax|yesno:"ajax_base.html,main_base.html" %}
Or:
{% extends a_variable_containing_base_template_name %}
Which ever best suited for you.
Regards;

django: how to interconnect various logical pieces of a webpage

everyone. I'm just starting with django, so sorry for a possibly stupid question.
Imagine, I have a webpage with 3 logical pieces: content, dynamic menu, banners. It seems ok to me to have a template with something like:
{% include "banners.html" %}
{% include "menu.html" %}
{% include "content.html" %}
But then, how do I do it? Every piece has its separate logic in a separate view in its' separate app. How do I trigger execution of all three views and render all three templates?
P.S. Is there a sourceforge-like site for django apps where I could take a look at how people are doing stuff in real projects?
The standard way to do it is something as follows:
Templates:
Have a base.html that has the banners, menu and a body block which is empty.
For each template, extend the base.html and override the body block.
{% extends "base.html" %}
{% block body %}
-- Your this page's content goes here.
{% endblock %}
You can use the includes, where necessary, but prefer the extends where possible. Include was debated to be included in the template language.
Populating Context:
You now have a lot of templates with placeholders that need to be replaced with the real "context" values.
Pass the RequestContext, that should contain many standard requirements for the template.
For the values that you need in every template, write a template context processor.
Those context's that you need in this template, you populate in the view.
Using multiple app's views:
Most apps written for reuse will include template_name as a standard parameter, along with extra_context. You will need to call those views with these parameters.
Some apps go out of their way, to create a lazily evaluated response (like TemplateResponse) so that you can grab the context they populate, in your view.
Django reusable apps:
Are you kidding me? They are all over the Internet!
http://github.com/search?q=django&type=Everything
http://bitbucket.org/repo/all/?name=django
http://code.google.com/hosting/search?q=django&projectsearch=Search+projects

Is there any reason why you can't compare a template filter to a string in Django template syntax?

I'm trying to do this, and failing. Is there any reason why it wouldn't work in Django template syntax? I'm using the latest version of Django.
{% ifequal entry.created_at|timesince "0 minutes" %}
It doesn't work because it's not supposed to work. What you're asking for is not part of the template language.
You can't apply a filter in the middle of tag like {% ifequal. When a template tag uses a variable, it doesn't expect an expression, it expects a variable, nothing more.
That kind of logic -- extracting time since, comparing, etc. -- is what you're supposed to do in your view function.
Your view function then puts a "zerominutes" item in the context for the template to use. Templates just can't do much processing.
They're designed to do the minimum required to render HTML. Everything else needs to be in your view function.
{% ifequal %} tag doesn't support filter expressions as arguments. It treats whole entry.created_at|timesince as identifier of the variable.
Quik workaround: introduce intermediate variable with expresion result using {% with %} like this:
{% with entry.created_at|timesince as delta %}
{% ifequal delta "0 minutes" %}
....
{% endifequal %}
{% endwith %}
See ticket #5756 and links in its comments for more information. A patch for Django in ticket #7295 implements this functionality. A broader refactoring of the template system based on #7295 is proposed in ticket #7806, and it would fix this issue among others.
I don't think making such comparisons to work would be against the design philosophy of Django templates.
I think you can, though I don't see any uses of it my code base. Maybe entry.created_at|timesince isn't producing the value you expect. Try putting
X{{entry.created_at|timesince}}X
into your template and seeing what value it produces. The X's are so you can see leading or trailing space, in case that is the problem.
I finally gave up on using the Django template language for anything other than the simplest pages. Check out Jinja2 for an almost-syntax-compatible alternative. And yes, you can choose which to use on a page-by-page basis.