Repeating HTML blocks in Django - django

Not sure what technical term it is I'm looking for, but I have a set of HTML elements that are repeated and wondering if there is an easy way to do this.
Very simplified HTML, if I have the following:
<div class='container'>
{{ django.dataFromORM }}
</div>
I need to add to base.html in a certain section
<div id='main-container'>
all elements go here
</div>
So on run, I want to add the generated HTML the main-container. I've done this before by building in JS, but wondering if there is a way to smoothly do this in Django?
I looked at templates and partials, but not sure that's the proper way or not?

You can use include in template to include your repeated html file.
ie
<div id='main-container'>
{% include "container.html" %}
</div>
if you want to repeat it several times you can add it inside a for loop
eg:
{% for element in elements %}
{% include "container.html" %}
{% endfor %}

Related

Django Templates - Best Practice in Avoiding Repeating Code that Require Different For Loops?

I'm creating a blog and have numerous pages that will display a list of articles. So, to avoid repeating that code, I'm trying to place it within a parent template that I can extend where needed.
The problem is I'll need a different for loop to display the article lists on each page/view. I figure the easiest approach would be to simply create blocks where I want the loop to start and close within the parent, then alter accordingly within each child.
However, Django doesn't allow you to close blocks that have an open for loop, despite closing the loop later in a different block.
My initial approach, in the parent, article_list.html:
<div class="row">
{% block loop_start %}
{% endblock loop_start %}
<div class="col-xs-12 col-sm-4">
<div class="card">
<a class="img-card">
<img class="img-fluid"src="../../static/{{ post.featured_image }}" />
</a>.... etc
I know I have to fix my src code.
Extends to child as:
{% block loop_start %}
{% for post in recent_articles %}
{% endblock loop_start %}
However, that doesn't work as noted above.
I've also tried wrapping the entire code for the article list in a block, extending it and performing the following within the child:
{% for post in recent_articles %}
{% block.super article_list %}
{% endblock article_list %}
{% endfor %}
That doesn't work either. Again, producing the same error as a block is closing before the loop ends. I've also tried closing the loop in the parent which doesn't work either.
Is there an easier way of going about this that I'm missing? I could pass the same variable to each view then implement the loop in the parent, but that seems janky and limiting.
What's best practice here?
You should take a look at a 'base.html' file. Take a look at this web-page: https://ultimatedjango.com/learn-django/lessons/create-the-project-base-template/
This will allow you to do {% extends 'base.html' %} all of which Django will handle.

Detecting a URL in a Django wizard_form.html template

I have three SurveyWizardViews all of which use the same standard wizard_form.html which is located at templates/formtools/wizard/wizard_form.html as per the documentation
I have added some basic logic to this template which is designed to detect which page of the form the user is on so that I can include a non standard page/step, this is an image with a JS slider bar underneath. This all works perfectly.
{% if wizard.steps.current == '6' %}
<img src="{% static "survey/images/pathtwo/" %}{{display_image}}"/>
<section>
<span class="tooltip"></span>
<div id="slider"></div>
<span class="volume"></span>
</section>
{% endif %}
However I now want to have a slightly different experience for the user depending on which View/URL they are coming from.
Question Is it possible to detect which URL the view is currently using to look at the page? e.g.
{% if URL.current == 'www.mywebsite.com/experiment/surveyone/' %}
do X
{% if URL.current == 'www.mywebsite.com/experiment/surveytwo/' %}
do y
I have done some searching but Im not even sure what I'm searching for to be honest. Any help would be much appreciated.
You can use the request context variable. Something like:
{% if 'experiment/surveyone' in request.path %}
do this
{% endif %}
I prefer using in instead of == to ignore trailing and leading slashes. If you want the whole thing try the build_absolute_uri method. Also check what options does request offer to you (https://docs.djangoproject.com/en/dev/ref/request-response/#httprequest-objects).
Finally, don't forget to add django.core.context_processors.request to your TEMPLATE_CONTEXT_PROCESSORS (I think it is added by default).

Can I specify a multiline context variable/parameter when {% include %}ing a template?

I know that it is possible to set context variables when including a Django template from another template using
{% include "default_table.html" with table_header=table_header1 table_data=table_data1 %}
or
{% with "My data" as table_data %}
{% include 'default_table.html' %}
{% endwith %}
My issue with this is that both approaches don't let me define multiline variables (unless they are based on a previous multiline variable of course).
My specific usecase is this
<!-- widget.html -->
<div class="box">
<div class="title">{{ title }}</div>
<div class="title">{{ body }}</div>
</div>
and I'd like to be able to set a longer text for the body context variable. This will make is possible for me to reuse common widget HTML in various places. Can this be done?
I've been searching a bit on http://djangosnippets.org for an über {% with ... %} template tag, but haven't found any so far.
This Django snippet kinda solves my issue: http://djangosnippets.org/snippets/1860/ But I'd love to be able to set context variables instead of defining {% localblock step_ready_js %}{% endlocalblock %} in my widget HTML.

Django template inclusion

The template inheritance page on the django site doesn't really solve my problem (Django 1.2).
My base page looks like:
...
<div class="grid_12" id="content">
{% block content %}{% endblock %}
</div>
...
{% block javascript %}{% endblock %}
I have another template that defines content for these:
{% block content %}
animated sidebar
{% endblock %}
...
{% block javascript %}
alert('hello');
{% endblock %}
This is something like an animated sidebar, so I don't want to extend the base template since it's auxiliary to the main content of the page. If I just use "include", the entire thing is put where the "include" tag is placed - as a result the javascript doesn't run because it's included before one of its dependencies.
What's the best way to solve this?
EDIT
Sorry, I didn't make myself clear.
I have my content pages which render a template that extends "base.html". In "base.html" I want to include a sidebar template that needs to append blocks in "base.html". So I've tried just putting include "sidebar.html" into "base.html", but it just inserts the whole thing where the "include" tag is. What I want it to do is append the blocks in "base.html", which may themselves have been populated by "page.html".
Maybe it's important to say that "sidebar.html" is entirely static - i.e. there's no callable associated with it. So perhaps this question should really be "How can I include a static template into base.html so it will append to blocks in base.html regardless of the output of the actual view that processes the request?"
I think you mean you want to append to a block? You can put {{ block.super }} where you want the inherited content to go. e.g.:
{% block javascript %}
{{ block.super }}
alert('hello');
{% endblock %}
You should only use {% block foo %} tags to extend blocks in a base template, so I'm not clear what you mean when you say you don't want to extend it.
The code, as you've entered it, should render to
...
<div class="grid_12" id="content">
animated sidebar
</div>
...
alert(hello)
Unless you want to append the content (as in Matt's answer) it's not clear what you want to happen.
You shoud be using something like jQuery to trigger execution only after the page is fully loaded. Include jQuery library in the document header and then somewhere:
$(document).ready(function() {
//your code goes here
});

How to test for use of a django template block?

I would like to do the following:
{% if appnav %}
<hr />
<div id="appnav">
<ul class="tabs">
{% block appnav %}{% endblock %}
</ul>
</div>
{% endif %}
...however, testing for the present use of a block by templates further down the inheritance chain does not seem to work.
Is there some other conditional that might do this?
The template language doesn't provide exactly what you're looking for. Child templates can call the parent block with {{ block.super }}, but parent templates can't reference child templates.
Your best bet will probably be to write a custom template tag. There are two sections in the template manual to review.
First, Parsing until another block tag. This will give you the basics of how to parse.
Second, Parsing until another block tag and saving contents. By placing a block tag inside the custom tag, you could detect content and wrap it as appropriate. This should work, because I believe the inner block tag will be parsed first. If that doesn't work, subclass the existing block template tag provided by django to implement your special magic.
If you you are looking for an easy solution. You can hide the element as the default html.
<div id="appnav">
<ul class="tabs">
{% block appnav %}
<script>document.getElementById("appnav").style.display = "none"</script>
{% endblock %}
</ul>
</div>