Home > Software design >  Images are not rendering on Django template from a multi-model view
Images are not rendering on Django template from a multi-model view

Time:05-07

Problem: I cannot get images to appear on my template plant_detail.html. I think I'm calling on variables incorrectly, but not sure what to change.

Context:

I created a model PlantImage, that allows me to associate multiple images within my model Plant.

I then created a class-based view PlantDetailView to link the two models, PlantImage and Plant together.

However, now when I try to display those images in the template plant_detail.html, nothing will appear. How can I get images to appear on my template?

I tried reading through the Django documentation, reading articles, and watching youtube videos, but I'm not sure what I'm missing or need to edit.

My files:

plants/models.py

class Plant(models.Model):
    name = models.CharField(max_length=120)
    slug = models.SlugField(null=False, unique=True)
    description = models.TextField()

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse("plant_detail", kwargs={"slug": self.slug})

class PlantImage(models.Model):
    plant = models.ForeignKey(Plant, default=None, on_delete=models.CASCADE)
    images = models.ImageField(upload_to = 'images/')
 
    def __str__(self):
        return self.plant.name

plants/views.py

def plant_index(request):
    plant_objects = Plant.objects.all()
    context = {'plant_objects': plant_objects}
    return render(request, 'plants/plant_index.html', context)

class PlantDetailView(DetailView):
    model = Plant
    template_name = 'plants/plant_detail.html'
    slug = 'slug'

    def get_context_data(self, **kwargs):
        context = super(PlantDetailView, self).get_context_data(**kwargs)
        context['plant_images'] = PlantImage.objects.all()
        return context

plant_detail = PlantDetailView.as_view()

plants/urls.py

from django.urls import path
from .views import plant_index, plant_detail

app_name = 'plants'
urlpatterns = [
    # ex: /plants/
    path('', plant_index, name='plant_index'),
    # ex: /plants/pothos/
    path("<slug:slug>", plant_detail, name="plant_detail"),
]

plants/plant_detail.html

{% block content %}
<body>
    <h1> {{ plant.name }} </h1>
    <br>
    <p> <b>Latin Name: </b>{{ plant.latin_name }} </p>
    <br>
    <p><b>Description: </b></p>Dj
    <p> {{ plant.description }} </p>
    <br>
    <br>
    <p>Images:</p>
    <br>
    {% for image in plant_images %}
    <p><img src="{{ plant.images }}" width="300px"></p>
    {% endfor %}
</body>
{% endblock content %}

settings.py

MEDIA_URL = '/media/'
MEDIA_ROOT = str(BASE_DIR.joinpath('mediafiles'))

Screenshots of output: Screenshot of the template page no showing the plant

Screenshot of the model in admin: Screenshot of the admin view for the combined model

CodePudding user response:

The code "PlantImage.objects.all()" gets not only specific image related plant but another images.

so if you want to access PlantImage from Plant, you have to write related_name.

https://docs.djangoproject.com/en/4.0/ref/models/fields/#django.db.models.ForeignKey.related_name

class PlantImage(models.Model):
    plant = models.ForeignKey(Plant, default=None, on_delete=models.CASCADE, related_name="plant_images")
    ...

ImageField inherit FileField. so, you have to know something of Filefield functions.

https://docs.djangoproject.com/en/4.0/ref/models/fields/#filefield-and-fieldfile

if you want to show images, add '.url' like this.

{% for image in plant.plant_images.all %}
<p><img src="{{ image.images.url }}" width="300px"></p>
{% endfor %}
  • Related