not able to align images in bootstrap - html

I am trying to make a gallery of images of unknown number using HTML. I am using bootstrap to display the images and have some django template library coding. I am not able to align the images correctly. I am basically trying to use cycle tag in Django Template to display the row class in bootstrap after every 2 images. I want the images to appear in a row, each row with two images. The height of each image in the row should be aligned correctly. Right now the height is not aligned. One image is slightly higher than the other. Can you please help, this is my html file?
<div class="container">
{% load staticfiles %}
{% for plot in plots%}
{% with plot|add:".png" as image_static %}`
<div class = "{% cycle 'row' '' %}">
<div class = "col-md-5">
<div class = "thumbnail">
<img src="{% static image_static %}" alt="My image"/>
</div>
<div class = "caption">
<h3>Thumbnail label</h3>
<p>Some sample text. Some sample text.</p>
<p>
<a href = "#" class = "btn btn-primary" role = "button">
Button
</a>
<a href = "#" class = "btn btn-default" role = "button">
Button
</a>
</p>
</div>
</div>
{% endwith %}
<br><br><br>
</div>
{% endfor %}
</div>

It cannot be done with cycle! Here's how it could be done instead:
{% for plot in plots%}
{% with plot|add:".png" as image_static %}
<div class='col-md-6'>
<div class = "thumbnail">
<img src="{% static image_static %}" alt="My image"/>
</div>
<!-- ... -->
</div>
{% if forloop.counter|divisibleby:"2" %}
</div>
<div class='row'>
{% endif %}
{% endwith %}
{% endfor %}
So, we close the row div and start a new one whenever the forloop index is divisible by 2, so we'll start a new row every two images!

Related

Django images don't fill height

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/

how to extend background color on column layouts css

I seem to be having trouble to extend my background color for my 2 column layout. The user can add categories so the background color has to be able to adjust with the amount of categories the user wants to add in.
html file:
{% for category in categories %}
<div class="row__2 sub-pages--background">
<div class="sub-pages--categories-background">
<div class="sub-pages--categories">
<a href="{% url 'blogging_logs:topics' category.id %}" class="sub-pages--categories-position ">{{ category }}
<img class="sub-pages--img" src="{{ category.category_image.url }}">
</a>
</div>
</div>
</div>
{% empty %}
<p>No categories entered yet.</p>
{% endfor %}
css file:
&--background {
background-color: $mainBackground;
padding-bottom: 2rem;
}
I feel like it has to do with the way I'm formatting my divs
Since you mentioned in comments that you are using floats, simply add a parent element that will have the background and then add something known as clearfix, at the end of it.
HTML:
<div class="parent--background">
{% for category in categories %}
<div class="row__2 sub-pages--background">
<div class="sub-pages--categories-background">
<div class="sub-pages--categories">
<a href="{% url 'blogging_logs:topics' category.id %}" class="sub-pages--categories-position ">{{ category }}
<img class="sub-pages--img" src="{{ category.category_image.url }}">
</a>
</div>
</div>
</div>
{% empty %}
<p>No categories entered yet.</p>
{% endfor %}
<div class="clearfix"></div>
</div>
CSS:
.clearfix::after {
content: "";
clear: both;
display: table;
}

Wrapping content with the same tags multiple times in Django templates

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>

Bootstrap 3 Displays Content Outside col-md-6 in Django Template

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

twig for loop put every 2 elements in a new container

I have this loop:
{% for div in myHandleHere %}
<div> {{ block.text }} </div>
{% endfor %}
That actually outputs something like:
<div> one </div>
<div> two </div>
<div> three </div>
<div> ... </div>
What I want is, every 2 div, put them in a new container, like:
<div class="container">
<div> one </div>
<div> two </div>
</div>
<div class="container">
<div> three </div>
<div> ... </div>
</div>
Please help
The best solution in this case is to use the great batch filter which allows to process elements in groups:
{% for pair in myHandleHere|batch(2) %}
<div class="container">
{% for element in pair %}
<div>{{ element }}</div>
{% endfor %}
</div>
{% endfor %}
What you want to do is either keep a count of which row you're on, or have a nested loop. Conveniently Twig has a couple of built-in loop variables we can use.
Something like this:
{% for div in myHandleHere %}
{% if loop.index is odd %}
<div class="container">
{% endif %}
<div> {{ block.text }} </div>
{% if loop.index is even or loop.last %}
</div>
{% endif %}
{% endfor %}
Loop over all your blocks. On each iteration, if the loop counter is odd, i.e. blocks 1, 3, 5 etc, start a new <div class="container">.
And if the loop counter is even, i.e. blocks 2, 4, 6 etc, close that </div>.
Also if you're on the last block, make sure and close the parent div too, e.g. in case you only have an odd number of blocks, you want to output HTML like:
<div class="container">
<div> one </div>
<div> two </div>
</div>
<div class="container">
<div> three </div>
<div> four </div>
</div>
<div class="container">
<div> five</div>
</div>