Django display limited images in grid row
Question:
As mentioned in the title. Is it possible to display a specific number of photos in a particular grid-container? For example, a maximum of 3 columns with a card in the row using a loop?
I was able to achieve the effect of displaying all the photos from the defined model,but I don’t know how to set the limit.
Below I present fragments of the code responsible for displaying the created model
forms.py
class ProductsForm(forms.ModelForm):
class Meta:
model = Product
fields = ('name', 'description', 'image', 'file_type')
models.py
class Product(models.Model):
name = models.CharField(max_length=20, default='')
description = models.CharField(max_length=100, default='')
file_type = models.CharField(max_length=256, choices=[('image', 'image'), ('thumbnail', 'thumbnail')], default='')
image = models.ImageField(upload_to='products', default='')
def __str__(self):
return self.name
views.py
def gallery(request):
image = Product.objects.filter(file_type='image')
thumbnail = Product.objects.filter(file_type='thumbnail')
return render(request, 'products/fruits.html', {'img': image, 'thumb': thumbnail})
fruits.html
<!DOCTYPE html>
{% load staticfiles %}
{% load thumbnail %}
{% block body_block %}
<div class="grid-container">
<div class="card-deck">
{% for i in thumb %}
{% thumbnail i.image "150x150" crop="center" as im %}
<!-- Card -->
<div class="card mb-4">
<!--Card image-->
<div class="view overlay">
<img src="{{ im.url }}"
alt="Card image cap">
<a href="#!">
<div class="mask rgba-white-slight"></div>
</a>
</div>
<!--Card content-->
<div class="card-body">
<!--Title-->
<h4 class="card-title">Card title</h4>
<!--Text-->
<p class="card-text">Some quick example text to build on the card title and make up
the
bulk
of
the
card's
content.</p>
<!-- Provides extra visual weight and identifies the primary action in a set of buttons -->
<button type="button" class="btn btn-light-blue btn-md">Read more</button>
</div>
</div>
{% endthumbnail %}
{% endfor %}
</div>
</div>
{% endblock %}
Answers:
The build-in Django filter divisibleby
may work, inside your loop, you check whether the iteration is divisible by (in your case) 3
, then you break the row to jump to another one:
{% for i in thumb %}
{% if forloop.counter|divisibleby:3 %}
----------
{% endif %}
{% endfor %}
I was able to get what you want to do by creating a list of lists of images in the view, then send this list to the HTML template and display it with two loops. The advantage of this approach is that you can control the number of columns by changing one variable. Each element of the main list contains X number of columns.
The idea is to send a list like the one represented below (more or less)
photos_list = [[photo1, photo2, … photoN], [photo1, photo2, … photoN]]
the view code is:
def index(request):
photos = Photo.objects.all()
counter = -1
columns_qty = 5 # << Just change this number for the columns you want
photos_row = []
photos_list = []
for photo in photos:
counter += 1
if counter < columns_qty:
photos_row.append(photo)
else:
photos_list.append(photos_row)
photos_row = []
counter = -1
context = {'photos_list': photos_list}
return render(request, 'photos/index.html', context)
the model code is:
class Photo(models.Model):
file_name = models.CharField(max_length= 250)
original_path = models.CharField(max_length=250)
saved_path = models.CharField(max_length=250)
file_size = models.IntegerField(null=True)
file_created = models.DateTimeField(null=True)
file_last_modified = models.DateTimeField(null=True)
loaded_datetime = models.DateTimeField(default=timezone.now())
def __str__(self):
return self.file_name
and the html template code is:
{% extends 'photos/base.html' %}
{% load static %}
{% block content %}
<table>
{% for photo_row in photos_list %}
<tr>
{% for photo_col in photo_row %}
<td><img src="{% static photo_col.file_name %}" width="300px"
height="auto"></td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endblock %}
I hope this helps!
As mentioned in the title. Is it possible to display a specific number of photos in a particular grid-container? For example, a maximum of 3 columns with a card in the row using a loop?
I was able to achieve the effect of displaying all the photos from the defined model,but I don’t know how to set the limit.
Below I present fragments of the code responsible for displaying the created model
forms.py
class ProductsForm(forms.ModelForm):
class Meta:
model = Product
fields = ('name', 'description', 'image', 'file_type')
models.py
class Product(models.Model):
name = models.CharField(max_length=20, default='')
description = models.CharField(max_length=100, default='')
file_type = models.CharField(max_length=256, choices=[('image', 'image'), ('thumbnail', 'thumbnail')], default='')
image = models.ImageField(upload_to='products', default='')
def __str__(self):
return self.name
views.py
def gallery(request):
image = Product.objects.filter(file_type='image')
thumbnail = Product.objects.filter(file_type='thumbnail')
return render(request, 'products/fruits.html', {'img': image, 'thumb': thumbnail})
fruits.html
<!DOCTYPE html>
{% load staticfiles %}
{% load thumbnail %}
{% block body_block %}
<div class="grid-container">
<div class="card-deck">
{% for i in thumb %}
{% thumbnail i.image "150x150" crop="center" as im %}
<!-- Card -->
<div class="card mb-4">
<!--Card image-->
<div class="view overlay">
<img src="{{ im.url }}"
alt="Card image cap">
<a href="#!">
<div class="mask rgba-white-slight"></div>
</a>
</div>
<!--Card content-->
<div class="card-body">
<!--Title-->
<h4 class="card-title">Card title</h4>
<!--Text-->
<p class="card-text">Some quick example text to build on the card title and make up
the
bulk
of
the
card's
content.</p>
<!-- Provides extra visual weight and identifies the primary action in a set of buttons -->
<button type="button" class="btn btn-light-blue btn-md">Read more</button>
</div>
</div>
{% endthumbnail %}
{% endfor %}
</div>
</div>
{% endblock %}
The build-in Django filter divisibleby
may work, inside your loop, you check whether the iteration is divisible by (in your case) 3
, then you break the row to jump to another one:
{% for i in thumb %}
{% if forloop.counter|divisibleby:3 %}
----------
{% endif %}
{% endfor %}
I was able to get what you want to do by creating a list of lists of images in the view, then send this list to the HTML template and display it with two loops. The advantage of this approach is that you can control the number of columns by changing one variable. Each element of the main list contains X number of columns.
The idea is to send a list like the one represented below (more or less)
photos_list = [[photo1, photo2, … photoN], [photo1, photo2, … photoN]]
the view code is:
def index(request):
photos = Photo.objects.all()
counter = -1
columns_qty = 5 # << Just change this number for the columns you want
photos_row = []
photos_list = []
for photo in photos:
counter += 1
if counter < columns_qty:
photos_row.append(photo)
else:
photos_list.append(photos_row)
photos_row = []
counter = -1
context = {'photos_list': photos_list}
return render(request, 'photos/index.html', context)
the model code is:
class Photo(models.Model):
file_name = models.CharField(max_length= 250)
original_path = models.CharField(max_length=250)
saved_path = models.CharField(max_length=250)
file_size = models.IntegerField(null=True)
file_created = models.DateTimeField(null=True)
file_last_modified = models.DateTimeField(null=True)
loaded_datetime = models.DateTimeField(default=timezone.now())
def __str__(self):
return self.file_name
and the html template code is:
{% extends 'photos/base.html' %}
{% load static %}
{% block content %}
<table>
{% for photo_row in photos_list %}
<tr>
{% for photo_col in photo_row %}
<td><img src="{% static photo_col.file_name %}" width="300px"
height="auto"></td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endblock %}
I hope this helps!