I'm using Flask for a small web app and having trouble to get my background image to display after extending using Jinja.
My layout.html contains a header:
<!-- Header section -->
<header class="header-section">
<div class="header-warp">
<div class="container">
<a href="#" class="site-logo">
<img src="{{ url_for('static', filename='img/logo.png') }}" alt="">
</a>
<div class="user-panel">
{%if session.user_id %}
Logout
{% endif %}
</div>
<div class="nav-switch">
<i class="fa fa-bars"></i>
</div>
</div>
</div>
</header>
<!-- Header section end -->
<main>
{% block main %}
{% endblock %}
</main>
And in another html file, I want to extend the layout:
{% extends "layout.html" %}
{% block title %}
Register
{% endblock %}
{%block main%}
<section class="hero-section set-bg" data-setbg="{{ url_for('static', filename='img/review-bg.jpg') }}">
However, the review-bg.jpg doesn't load and instead, I received a blank section. However, when I straight up copying the layout (not using extends anymore), the image loaded correctly. I double checked with (http://127.0.0.1:5000/static/img/review-bg.jpg) and the path correctly return the image.
Anyone can help explain to me why Jinja doesn't load the image after extending?
The problem seems to be in data-setbg - it can be React script, look here:
html tag attribute "data-setbg" is not working in React project
Or try to google "data-setbg is not working"
Edit the extension to:
{% extends "layout.html" %}
{% block title %}
Register
{% endblock %}
{%block main%}
<img src="{{ url_for('static', filename='img/review-bg.jpg') }}" alt="">
Do you see the image now? If so (what I suspect), it's not jinja/flask related but something else is going on. If not, right click on the page in firefox and press view source. Where is the link pointing to?
Related
Need help please. I'm trying to get this if statement within a for statement correct, but failing miserably at it. If an image isn't available, I badly need a fallback image to replace it.
Thank you
{% for post in posts|slice:":1" %}
<div class="container">
{% if post.image.url %}
<div class="flex-item">
<img style="width:100%;" src="{{ post.image.url }}"
</div>
{% else %}
<div class="image-container1">
<img src="{% static 'images/fallback.png' %}" alt="" style="width: 100%;text-align: center;display: block;">
</div>
{% endif %}
{% endfor %}
You are not closing a div, which you opened just after first loop, also assuming that you are loading static on top.
P.S. I can't add comment, so posting it as ans.
I am using django-ckeditor as a WYSIWYG text editor when creating posts. It captures and saves the content and the correct HTML tags without any problem. However, my template renders the variable surrounded by <p> tags, which ruins the RichTextField because <p> tags cannot be nested. As a result, it was showing all of the text (with tags) as a paragraph with no formatting. I realized that this was happening, so I changed the surrounding tags in my template to <div> tags, but when the template is loaded on the browser, it replaces the div tags with paragraph tags again. How can I get rid of the <p> tags so that my text is rendered with the correct formatting?
Here is my template:
{% extends 'bandwagon/base.html' %}
{% block content %}
<article class="media content-section">
<img src="{{ post.author.profile.image.url }}" alt="profile photo" class="rounded-circle article-img">
<div class="media-body">
<img src="{{ post.image.url }}" class="post-img">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-posts' object.author.username %}">{{ object.author }}</a>
<small class="text-muted">{{ object.date_posted | date:'F d, Y'}}</small>
{% if object.author == user %}
<div>
Edit
Delete
</div>
{% endif %}
</div>
<h2 class='article-title-detail'>{{ object.title }}</h2>
<div class="article-content">{{ object.content | safe }}</div>
</div>
</article>
{% endblock content %}
However, in the browser, the response is this:
<p class="article-content"><h3>Fake Content</h3>
<h3><span style="font-size:13px">Fake Content</span></h3></p>
By default CKEditor RichTextField adds <p> tags around the content of the field.
If that's the reason you keep seeing <p> around your content, you can customizing your CKEditor editor, so it will not add the <p> like this:
#base.py
CKEDITOR_CONFIGS = {
'default': {
'autoParagraph': False
},
}
You can also create a specific configuration and set specific fields to use it.
read more about it here: https://django-ckeditor.readthedocs.io/en/latest/#optional-customizing-ckeditor-editor
I have the following html files.
banner.html
<header class="intro2">
<div class="intro-body">
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h1>{% block banner %}Bannertest{% endblock banner %}</h1>
</div>
</div>
</div>
</div>
</header>
test.html
{% extends 'banner.html' %}
{% block banner %}
Test
{% endblock banner %}
I'm new to Django but I would expect the H1 title to be updated to say Test instead of Bannertest?
What am I doing wrong?
You need to extend your main html not to include
replace
{% include 'banner.html' %}
to
{% extends "banner.html" %}
more details here: include-vs-extends
your full new html:
{% extends 'banner.html' %}
{% block banner %}Test{% endblock banner %}
For block overriding you must use {% extends 'banner.html' %} instead of {% include %}
So instead of making small fragments for include, like in php, standard approach is to make a full template, say base.html, when extend it in child templates.
{% include %} tag is better suits for widgets with parameters, e.g. {% include '_form.html' style='light' some_param=some_value %}
How do I display a group of 6 thumbnails in my template to create a filmstrip. The list i am iterating through a for loop has around 30 items i want to break it into chunks of 6 and show it as a filmstrip slider. I tried using the range function for the for loop but that doesnt work
<div class="carousel-inner">
<div class="item active">
<ul class="thumbnails">
{% for show in object_list %}
<li class="span2">
<div class="thumbnail">
<a href="{{ show.get_absolute_url }}" data-title="{{ show.name }}" >
{% if show.images.exists %}
{% with show.images.all.0.image as show_image %}
<img src="{% thumbnail show_image 160x160 crop %}" alt="{{show.name}}" class="thumbnail">
{% endwith %}
{% else %}
<img src="{% static 'img/default-image.gif' %}" alt="{{show.name}}" class="thumbnail">
{% endif %}
</a>
</div>
</li>
{%endfor%}
</ul>
</div>
If you want 1 carousel per 6 images then you could do it like this
Step 1) Create a new .html file in your templates folder called film-slider.html.
{% for reel in reels %}
<div class="carousel-inner">
<div class="item active">
<ul class="thumbnails">
{% for show in reel %}
<li class="span2">
<div class="thumbnail">
<a href="{{ show.get_absolute_url }}" data-title="{{ show.name }}" >
{% if show.images.exists %}
{% with show.images.all.0.image as show_image %}
<img src="{% thumbnail show_image 160x160 crop %}" alt="{{ show.name }}" class="thumbnail">
{% endwith %}
{% else %}
<img src="{% static 'img/default-image.gif' %}" alt="{{ show.name }}" class="thumbnail">
{% endif %}
</a>
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endfor %}
Step 2) In your templatetags/tags.py (create it if you haven't)
from django import template
register = template.Library()
def filmslider(reel):
reels = []
for i in range(0, len(reel), 6):
reels.append(reel[i:i+6])
return {'reels':reels}
register.inclusion_tag('film-slider.html')(filmslider)
This will make an inclusion tag that's available in your templates once you've loaded it via {% load tags %}.
This will make this work for you like this {% filmslider object_list %} which you will replace all the above html code that you posted with.
I haven't tested this but it should work, if in the future you want to have more functionality to this tag you can simply add arguments to the tag definition, I'll give an example.
def filmslider(reel, slides):
#do the code.
which will lead you to {% filmslider object_list 9 %} and voila, now you can extend your film reel from 6 slides to 9.
Hope this helps a bit!
What is the Django way of creating a reusable template?
Example: Suppose a lot of my pages contain a "Latest News" box and following the DRY principle, I would like to define it once and reuse it in the other pages. How would I do this with Django (or Jinja2) templates?
Reading through Django's Template Documentation I get the impression that Django templates offer "top-down" inheritance where the sub-template itself determines in which super-template it is going to be embedded:
<!-- Super-template (not valid, for illustration): -->
<html>
<head><title>Title</title></head>
<body>{% block content %}{% endblock %}</body>
</html>
<!-- Sub-template: -->
{% extends "base.html" %}
{% block content %}
<div class="latest-news">News</div>
{% endblock %}
So what is the technique to reuse a block (a sub-template) in several places?
The most flexible way to reuse template fragments is to define an inclusion_tag. You can pass arguments to your custom tag, process them a bit in Python, then bounce back to a template. Direct inclusion only works for fragments that don't depend on the surrounding context.
Quick example from the docs:
In app/templatetags/poll_extras.py register the tag with a decoration:
from django import template
register = template.Library()
#register.inclusion_tag('results.html')
def show_results(poll):
choices = poll.choice_set.all()
return {'choices': choices}
In app/templates/results.html:
<ul>
{% for choice in choices %}
<li> {{ choice }} </li>
{% endfor %}
</ul>
Calling the tag:
{% load poll_extras %}
{% show_results poll %}
What you're looking for, is {% include "template.html"%} from Django docs.
If you need to use {% block %} you can only do that via the {% extend %} approach. Otherwise, you can use {% include 'some.html' %} to include a bit of HTML in multiple places.
The unofficial Django Reusable App Conventions recommends using these block names:
{% block title %}
{% block extra_head %}
{% block body %}
{% block menu %}
{% block content %}
{% block content_title %}
{% block header %} {% block footer %}
{% block body_id %} {% block body_class %}
{% block [section]_menu %} {% block page_menu %}
If everyone stuck to these conventions, it should make this problem easier. Follow the link to see the description of each block.
Example of using {% include %} tag
All data comes from Django back-end
Many values are passed to card_template.html using include tag in page1.html
card_template.html
<style>
.choices_div {
border-radius: 5rem;
}
.card-footer {
background-color: transparent;
border: transparent;
}
</style>
<div class="col mb-5 px-4">
<div class="card h-100 w-100 jumbotron choices_div {{ bg_color|default:'' }}">
<div class="card-body p-0">
<h3 class="card-title text-center">{{ card_title|capfirst }}</h3>
<ul class="card-text mt-3">
{% for c in card_body_list %}
<li>{{ c }}</li>
{% endfor %}
</ul>
</div>
<div class="card-footer text-center pt-4">
{% if get_post_request == 1 %}
<a class="btn btn-light" href="{{ href }}">{{ button_text }}</a>
{% else %}
<form method="post">
{% csrf_token %}
<button type="submit" class="btn btn-light w-75" name="category"
value="{{ button_value }}">{{ button_text }}</button>
</form>
{% endif %}
</div>
</div>
</div>
page1.html
{% extends 'core/core.html' %}
{% block body %}
<div class="jumbotron bg-white">
<div class="container">
<div class="mb-5 text-center">
<h1>Choose user category</h1>
<h5>Once choosen, the user category cannot be changed</h5>
</div>
<div class="row row-cols-lg-2 justify-content-around">
{% for object in object_list %}
{% cycle 'bg_peacock' 'bg_sunset' 'bg_skin' 'bg_brown' as bg_color silent %}
{% include 'core/card_template.html' with card_title=object.category card_body_list=object.description get_post_request=2 button_text='Select' bg_color=bg_color button_value=object.id %}
{% endfor %}
</div>
</div>
</div>
{% endblock %}
As other answers have mentioned, the simplest approach is direct inclusion:
{% include 'mytemplate.html' %}
It is possible to modify the context of the rendered template (Or in simpler terms, to pass variables to the template) using
{% include 'mytemplate.html' with poll=poll %}
To use the traditional polls example, the template I would write would be:
<div class="stylish-poll">
{% for choice in poll.choices %} <!-- poll is a template variable -->
{% include 'choice_template.html' with choice=choice %}
{% endfor %}
</div>
Another potentially useful thing to know is that the only keyword prevents the template variable poll being passed into 'choice_template.html' which it would be by default. If you do not want the choice template to have access to {{ poll }} then the include statement looks like:
{% include 'choice_template.html' with choice=choice only %}
Documentation: https://docs.djangoproject.com/en/dev/ref/templates/builtins/#include
Aïe, my fault – the answer is given in the Django Reference (and not discussed in the aforementioned Django Template Documentation)…
So: Just use {% include sub_template_name %}.
even though the question is asked years ago, any way I will show you the method that worked for me.
base.html
In your base template you need to define all of your blocks that you need to reuse in your other templates,
<html>
<head>
<meta name="description" content="{%block description%}{%endblock%}">
<meta name="keywords" content="{%block keywords%}{%endblock%}">
<title>{%block title%}{%endblock%}</title>
</head>
<body>
<!---other body stuff--->
{%block content%}
{%endblock%}
</body>
</html>
home.html
{%extends 'base.html'%}
<!--you can reuse all blocks here-->
{%block description%}Django reusable blocks, for every bage{%endblock%}
{%block keywords%}django,block, resuable,meta,title,{%endblock%}
{%block title%}django reuseable blocks for title, meta description and meta keywords{%endblock%}
{%block content%}
<div>
<h1> reuse blocks</h1>
</div>
{%endblock%}