Search code examples
pythondjangodjango-modelsdjango-template-filters

Django template displaying images in wrong position


I'm new to Django so apologies if this one is silly. I have a Django template with three spots for images, and I'm trying to let an admin user choose which image in the database should go in which spot (left, middle or right). However,

My model looks like this:

from django.db import models
from django.urls import reverse
from django.utils.text import slugify

class Artwork(models.Model):

    art = models.ImageField(upload_to='artworks/%Y')
    title = models.CharField(max_length=200)
    description = models.TextField(null=True, blank=True)
    date = models.DateField(auto_now_add=True)
    herochoices = [('left', 'left'), ('middle', 'middle'), ('right', 'right')]
    hero = models.CharField(choices=herochoices, max_length=6, unique=True, null=True, blank=True, error_messages={'unique':'Another artwork already uses this hero position.'})  
    slug = slugify(title, allow_unicode=False)

    def get_absolute_urls(self):
        return reverse('artwork_list', kwargs={'slug': self.slug})

And my template looks like this:

{% extends 'base.html' %}

{% block content %}

<div class="container">
    <div class="row">
        {% for artwork in object_list %}
            {% if artwork.hero == 'left' %}
                <div class="col-sm p-3 align-items-center">
                    <img class="img-fluid rounded" src="{{ artwork.art.url }}" />
                    <p>{{ artwork.hero }}</p> <!--for testing-->
                </div>
            {% elif artwork.hero == 'middle' %}
                <div class="col-sm p-3 align-items-center">
                    <img class="img-fluid rounded" src="{{ artwork.art.url }}" />
                    <p>{{ artwork.hero }}</p> <!--for testing-->
                </div>
            {% elif artwork.hero == 'right' %}
                <div class="col-sm p-3 align-items-center">
                    <img class="img-fluid rounded" src="{{ artwork.art.url }}" />
                    <p>{{ artwork.hero }}</p> <!--for testing-->
                </div>
            {% endif %}
        {% endfor %}
    </div>
</div>

{% endblock content %}

For some reason the images are displayed in the wrong order:

enter image description here

I have been looking at this for forever, any help is much appreciated!


Solution

  • The template you are generating with Django is not the following, since the for loop does simply follow the queryset items order.

    <div class="container">
      <div class="row">
        <div class="col-sm p-3 align-items-center">
          <img class="img-fluid rounded" src="{{ LEFT URL }}" />
          <p>{{ LEFT HERO }}</p>
        </div>
        <div class="col-sm p-3 align-items-center">
          <img class="img-fluid rounded" src="{{ MIDDLE URL }}" />
          <p>{{ MIDDLE HERO }}</p>
        </div>
        <div class="col-sm p-3 align-items-center">
          <img class="img-fluid rounded" src="{{ RIGHT URL }}" />
          <p>{{ RIGHT URL }}</p>
        </div>
      </div>
    </div>
    

    In this snippet, three images will be ordered. If you have more than three, you should make the queryset "smarter" (i.e. a simple get won't work).

    URL:

    def example(request):
        qs = Artwork.objects.all()
        objects_list = [qs.get(hero=position) for position in ["left", "middle", "right"]]
        return render("test.html", { "objects_list": objects_list})
    

    HTML:

    {% extends 'base.html' %}
    
    {% block content %}
    
    <div class="container">
      <div class="row">
        {% for artwork in object_list %}
        <div class="col-sm p-3 align-items-center">
          <img class="img-fluid rounded" src="{{ artwork.art.url }}" />
          <p>{{ artwork.hero }}</p>
          <!--for testing-->
        </div>
        {% endfor %}
      </div>
    </div>
    
    {% endblock content %}