I am working on a simple web-application with flask and am currently trying to dynamically create a scrollspy list group with jinja. In the code snippet the variable "choices" represents a list of lists of dictionaries. So the variable dict will be a list of dictionaries that populates the ids needed for the list group to work. For simplicity, I am testing it with choices containing only one list of dictionaries and loop.index to create the ids, but I was going to change that to uniquly generated ids later as choices will have more elements.
Unfortunately, the list group does not work properly. Any ideas as to what I'm doing wrong? The browser console throws me an error, "uncaught TypeError: i is null", relating to the bootstrap scrollspy.js. I was not able to trace it back and figure out what causes the error.
{% extends "layout.html" %}
{% block title %}
Results
{% endblock %}
{% block main %}
<!--course display-->
{% for i in choices %}
<div class= "container-fluid">
<div class="row justify-content-center">
<div class="col-9 heading">
<div>
<h1>Coursera Courses</h1>
</div>
</div>
</div>
<div class="row justify-content-center result-background">
<div id="list-example" class="col-2 list-group">
{% for dict in i%}
<a class="list-group-item list-group-item-dark list-group-item-action" href="#list-item-{{ loop.index }}">{{ dict["Course Name"] }}</a>
{% endfor %}
</div>
<div class="col-7">
<div class="scrollspy-example" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-offset="40" tabindex="0">
{% for dict in i %}
<div class="boxlayout" id="#list-item-{{ loop.index }}">
<img src="{{ dict["Image URL"] }}" alt="responsive webite" class="img-thumbnail" align="left" width="15%" height="15%">
<h2>{{ dict["Course Name"] }}</h2>
<details close>
<summary>Lorem ipsum</summary>
Lorem ipsum
</details>
</br>
<table>
<tr>
<td>Manufacturer</td><td> </td>
<tr>
<td>Certificate</td><td>{{ dict["Certificate"] }}</td>
</tr>
<tr>
<td>Costs</td><td>${{ dict["Current Price"] }}</td>
</tr>
<tr>
<td>Landing Page</td>
</tr>
</table>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% endfor %}
{% endblock %}
The CSS I use as per the Bootstrap requirements:
.scrollspy-example{
position: relative;
overflow-y: scroll;
height: 300px;
}
Related
Attached is the wagtail template I have written so far.
{% load wagtailimages_tags %}
<section class="container">
<h2 class="text-center">{{ self.title }}</h2>
<div class="general-alumnae-deck">
{% for member in self.general_member_cards %}
{% if member.photo %}
{% endif %}
{% endfor %}
</div>
</section>
Ultimately I want the code to look like:
<h2>Avatar Images</h2>
<ul>
<li><img src="img_avatar.png" alt="Avatar" class="avatar"> <h3> Bleu </h3></li>
<li><img src="img_avatar2.png" alt="Avatar" class="avatar"> <h3> Red </h3></li>
</ul>
</body>
</html>
with the image popping up next to the "h3" tag if there exists a photo of course the image will be {{}} double bracketed for dynamic template.
It's not clear whether the image is from Wagtail's image library, but if it is, you should use the {% image %} tag. See https://docs.wagtail.org/en/stable/topics/images.html#
{% with self.general_member_cards as cards %}
{% if cards %}
<ul>
{% for member in cards %}
<li>
{% if member.photo %}
{% image member.photo fill-80x80 %}
{% endif %}
<h3>{{ member.name }}</h3>
</li>
{% endfor %}
<ul>
{% endif %}
I have also used a {% with %} tag to cache self.general_member_cards in the template, in case this requires a database query. If it does not, you can skip that step.
You more or less have it already ...
<section class="container">
<h2 class="text-center">{{ self.title }}</h2>
<div class="general-alumnae-deck">
<ul>
{% for member in self.general_member_cards %}
<li>
{% if member.photo %}
{% image member.photo fill-50x50 as avatar %}
<img src="{{ avatar.url }} class='avatar">
{% endif %}
<h3 style="display:inline;">{{ member.name }}</h3>
</li>
{% endfor %}
</ul>
</div>
</section>
You said you wanted image next to the <h3>, so you need to override the display:block property of the h3 tag and make it inline as above (or create a css class for this).
EDIT: Updated to use wagtail's image template tag to get the rendition of the member photo
I am currently working on a django blog. However, I am experiencing some difficulties with the size of the post thumbnails. Here's a picture:
What I marked in yellow is how the image should be filling the space. The width is fine, but the heigh isn't working well as you can see.
Here's the code:
{% extends 'base.html' %}
{% load static %}
{% block content %}
<style>
img {
height: 100%;
width: 100%;
}
</style>
<!-- Post-->
{% for obj in object_list %}
<div class="row d-flex align-items-stretch">
{% if not forloop.first and not forloop.last %}
<div class="image col-lg-5"><img src="{{ obj.thumbnail.url }}" alt="..."></div> #Here's the image
{% endif %}
<div class="text col-lg-7">
<div class="text-inner d-flex align-items-center">
<div class="content">
<header class="post-header">
<div class="category">
{% for cat in obj.categories.all %}
{{ cat }}
{% endfor %}
</div>
<a href="{{ obj.get_absolute_url }}">
<h2 class="h4">{{ obj.title }}</h2>
</a>
</header>
<p>{{ obj.overview|linebreaks|truncatechars:200 }}</p>
<footer class="post-footer d-flex align-items-center"><a href="#" class="author d-flex align-items-center flex-wrap">
<div class="avatar"><img src="{{ obj.author.profile_picture.url }}" alt="..." class="img-fluid"></div>
<div class="title"><span>{{ obj.author }}</span></div></a>
<div class="date"><i class="icon-clock"></i> {{ obj.timestamp|timesince }} ago</div>
<div class="comments"><i class="icon-comment"></i>{{ obj.comment_count }}</div>
</footer>
</div>
</div>
</div>
{% if forloop.first or forloop.last %}
<div class="image col-lg-5"><img src="{{ obj.thumbnail.url }}" alt="..."></div> #Here's the image
{% endif %}
</div>
{% endfor %}
</div>
</section>
I have no idea where the error is. I've tried to debug the problem but I haven been able to debug it
The way I see it, it's doing exactly what it's supposed to.
You put the image inside a column, then the image has 100% of the width, and because this is just an image inside a div (no display flex on the column or tricks involved), 100% height is just not gonna work and the default height of the image is used.
And even if it did work, and the images where 100% both on height and width, they'll probably end up all stretched and deformed in different resolutions, because the ratio of width:height probably changes.
I usually skip this dilemma by avoiding the use of the img tag altogether, and setting the images as background-images in the column with the 'image' class. Then set the background-size to "cover", and background-position to "center". You probably also need to set a minimum height for this column, so the images don't completely disappear when the columns stack on top of each other on smaller screens.
You can add a class like
<style>
.image {
background-size: cover;
background-repeat: no-repeat;
background-position: center;
min-height: 200px; // this size is arbitrary, choose what suits best
}
</style>
And then add the image on the iteration like so
<div class="image col-lg-5" style="background-image: url('{{ obj.thumbnail.url }}');"></div>
first you install it using pip install easy-thumbnails
INSTALLED_APPS = [
# ...
'easy_thumbnails',
]
then you do your migrations,and use it in your templates, this is from a project of mine:
{% load thumbnail %}
{% for image in images %}
<div class="image">
<a href="{{ image.get_absolute_url }}">
{% thumbnail image.image 300x300 crop="smart" as im %}
<a href="{{ image.get_absolute_url }}">
<img src="{{ im.url }}">
</a>
</a>
</div>
{% endfor %}
you can play with the details 300x300 as you wish, also the crop is optional but very useful
if you have trouble showing images add : THUMBNAIL_DEBUG = True to your settings
here is the docs https://easy-thumbnails.readthedocs.io/en/
Given a base.html file containing the following:
<div class="foo some-content">
...content...
</div>
<div class="bar some-content">
...different content...
</div>
I would like to wrap each of the .some-content divs to achieve a nested structure when using base.html in certain places:
<div class="row">
<div class="foo some-content">
...content...
</div>
</div>
<div class="row">
<div class="bar some-content">
...different content...
</div>
</div>
I tried extending base.html to wrap the divs with a .row div:
{% extends base.html %}
{% block wrapper %}
<div class "row">
{{ block.super }}
</div>
{% endblock %}
But that didn't work as I got a TemplateSyntaxError for using block wrapper twice in base.html:
# Throws TemplateSyntaxError
{% block wrapper %}
<div class="foo some-content">
...content...
</div>
{% endblock %}
{% block wrapper %}
<div class="bar some-content">
...different content...
</div>
{% endblock %}
I realize that I could break up the .some-content divs in to their own files, and reuse those in other places, but I would prefer another route. I also looked at Django template macros as suggested in this SO answer, but I think middleware will be overkill in this situation.
Is there any way I can extend or reuse my current base.html file so that the .some-content divs are sometimes wrapped in a .row div?
Could you do something like:
{% with foo as var %}
{% include 'mycontainer.html' %}
{$ endwith %}
{% with bar as var %}
{% include 'mycontainer.html' %}
{$ endwith %}
Then mycontainer.html would be:
<div class="row">
<div class="{{ var }} some-content">
...
</div>
</div>
Sorry this question is unavoidably kind of long.
I have basetemplate.html which other files extend.
basetemplate.html:
<!DOCTYPE html>
<html lang="en">
<head>....</head>
<body>
<nav class="navbar navbar-default navbar-fixed-top">...</nav>
<div class="container">
<div class="row">
<div class="col-md-3 hidden-xs hidden-sm">
{% block profile %}
<p>User details here...</p>
{% endblock %}
</div>
<div class = "col-md-6">
{% block mainBody %}
{% endblock %}
</div>
<div class = "col-md-3 hidden-xs hidden-sm">
{% block others %}
<p>Others here...</p>
{% endblock %}
</div>
</div>
</div>
</body>
</html>
I now have home.html extending basetemplate.html:
home.html:
{% extends "mysite/base.html" %}
{% block mainBody %}
{% include 'mysite/mainbody.html' %}
{% endblock %}
And mainbody.html contains:
{% for article in articles reversed %}
<div class="article-wrapper">
<div class="article-content">
<p>{{ article.content }}</p>
</div>
</div>
{% endfor %}
This works well for home.html. All my articles are displayed within <div class = "col-md-6"></div> but it doesn't for hashtags.html page. If I have, say 10 articles coming for a particular hashtag, it will display two or more within <div class = "col-md-6"></div> and may be three outside it and the rest outside <div class = "row"></div>. And sometimes some are even displayed outside <div class = "container"></div>.
hashtag.html:
{% extends "mysite/base.html" %}
{% block mainBody %}
{% include 'mysite/mainbody.html' %}
{% endblock %}
Query that fetches article for home.html is articles = Article.objects.all()[:10] while that of hashtag.html is articles = Article.objects.filter(content__icontains=hashtaggedword)[:10].
I have checked and checked to see if have any unclosed tag but couldn't find any even after using W3C Validator. I have also checked to see if there is something strange with those that display outside col-md-6 but they are okay and displayed in order of time they are created.
Probably article.content have html tags. Escape them by escape.
{{ article.content|escape }}
try using this way:
<ul class="list-group">
{% for article in articles reversed %}
<li class="list-group-item">{{ article.content }}</li>
{% endfor %}
</ul>
Result of this code is a simple list and you can put this to your column without any problem
I am using the http://www.highcharts.com/demo/gauge-speedometer on a page that dynamically renders multiple gauges. The gauges are grouped by their current level. I only want a maximum of 6 gauges in a row with any additional gauges to display on a new row.
The gauges are all working properly. However, if there are 7 gauges with a level of "red", they are flowing off the page.
My view returns a "gauge_list" which is a list of dictionaries for each gauge like this:
{'cnt': 48, 'yellow_to': 66, 'level': 'yellow', 'gauge_min': 0, 'gauge_link': 'gauges:contracts', 'green_to': 33, 'gauge_max': 100, 'gauge_title': 'contracts', 'gauge_name': 'Contracts'}
Any suggestions on the best way to handle this?
<div class="row">
<div class="span12">
<table>
{% for gauge in gauge_list %}
{% if gauge.level == "red" %}
<td><div id="{{gauge.gauge_title}}" style="width: 280px; height: 210px; margin: 0 auto"></div></td>
{% endif %}
{% endfor %}
</table>
</div>
</div>
<div class="row">
<div class="span12">
<table>
{% for gauge in gauge_list %}
{% if gauge.level == 'yellow' %}
<td><div id="{{gauge.gauge_title}}" style="width: 280px; height: 210px; margin: 0 auto"></div></td>
{% endif %}
{% endfor %}
</table>
</div>
</div>
<div class="row">
<div class="span12">
<table>
{% for gauge in gauge_list %}
{% if gauge.level == 'green' %}
<td><div id="{{gauge.gauge_title}}" style="width: 280px; height: 210px; margin: 0 auto"></div></td>
{% endif %}
{% endfor %}
</table>
</div>
</div>
I think the simplest way to do this is to either a) determine the grouped lists in the view or b) use the built-in groupby template tag. groupby requires that the list of dictionaries be arranged by the grouping key, which would be level here. That's best done in the view, since you probably don't want the naive alphabetic sorting that the dictsort filter would give you.
{% regroup gauge_list by level as level_list %}
{% for level in level_list %}
<div class="row">
<div class="span12">
<table>
{% for gauge in level.list %}
{% if forloop.counter0|divisibleby:"6" %}
{% if not forloop.first %}</tr>{% endif %}
<tr>
{% endif %}
<td><div id="{{gauge.gauge_title}}" style="width: 280px; height: 210px; margin: 0 auto"></div></td>
{% endfor %}
</tr>
</table>
</div>
</div>
{% endfor %}
By doing it in the view, I mean something like providing a nested data structure instead of a simple list. Something like:
levels_and_gauges = [['red', [...red guage dicts]],
['yellow', [...yellow guage dicts]],
['green'], [...green guage dicts]]]
The template code would then be something like this:
{% for level, guages in levels_and_guages %}
<div class="row">
<div class="span12">
<table>
{% for guage in guages %}
{% if forloop.counter0|divisibleby:"6" %}
{% if not forloop.first %}</tr>{% endif %}
<tr>
{% endif %}
<td><div id="{{gauge.gauge_title}}" style="width: 280px; height: 210px; margin: 0 auto"></div></td>
{% endfor %}
</tr>
</table>
</div>
</div>
{% endfor %}
Or you could group into 6-length rows in the view rather than the template.
{% for level in ["red", "yellow", "green"] %}
<div class="row">
<div class="span12">
<table>
{% for gauge in gauge_list %}
{% if gauge.level == level %}
<td><div id="{{gauge.gauge_title}}" style="width: 280px; height: 210px; margin: 0 auto"></div></td>
{% endif %}
{% endfor %}
</table>
</div>
</div>
{% endfor %}