djangodjango-modelsdjango-templatesdjango-template-filters

Django reference multiple image in template


Hi I am letting the user upload multiple images per project but so far the images are not displayed. In projects.html all projects should be displayed and the title and the describtion work so far. But the main-image doesn´t show up. In single-project all images should be displayed. What do I have to change in my models.py? Thanks in forward

models.py

class Project(models.Model):
    title = models.CharField(max_length=200)
    describtion = models.TextField(null=True, blank=True)
    id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)

class ProjectImage(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    featured_images = models.FileField()

forms.py

class ProjectForm(ModelForm):
    featured_images = forms.ImageField(widget=ClearableFileInput(attrs={'multiple':True}))
    class Meta:
        model = Project
        fields = ['title', 'describtion', 'featured_images']

views.py

def createProject(request):
    form = ProjectForm()

    if request.method == 'POST':
        form = ProjectForm(request.POST)
        images = request.FILES.getlist('image')
        if form.is_valid():
            project = form.save()
            for i in images:
                ProjectImage(project=project, image=i).save()

    context = {'form':form}
    return render(request, 'projects/project_form.html', context)

def projects(request):
    projects = Project.objects.all()
    context = {"projects":projects}
    return render(request, 'projects/projects.html', context)

def project(request, pk):
    projectObj = Project.objects.get(id=pk)
    return render(request, 'projects/single-project.html', {'project':projectObj})

projects.html

 {% for project in projects %}
          <div class="column">
            <div class="card project">
              <a href="{% url 'project' project.id %}" class="project">
                <img class="project__thumbnail" src="{{project.featured_images.url}}" alt="project thumbnail" />
                <div class="card__body">
                  <h3 class="project__title">{{project.title}}</h3>
                  <h3 class="project__title">{{project.price}} €</h3>
                </div>
              </a>
            </div>
          </div>
{% endfor %}

single-project.html

<h3 class="project__title">{{project.title}}</h3>
<h3 class="project__title">{{project.price}} €</h3>
<h3 class="singleProject__subtitle">Infos zum Produkt</h3>
{{project.describtion}}

project_form.html

            <form class="form" method="POST" enctype="multipart/form-data">
                {% csrf_token %}

                {% for field in form %}

                <div class="form__field">
                    <label for="formInput#text">{{field.label}}</label>
                    {{field}}
                </div>
                {% endfor %}

                <input class="btn btn--sub btn--lg  my-md" type="submit" value="Submit" />
            </form>

Solution

  • To access the images of a project, you need to use the related manager in your templates:

    projects.html

    {% for project in projects %}
              <div class="column">
                <div class="card project">
                  <a href="{% url 'project' project.id %}" class="project">
                    <img class="project__thumbnail" src="{{project.projectimage_set.all.0.featured_images.url}}" alt="project thumbnail" />
                    <div class="card__body">
                      <h3 class="project__title">{{project.title}}</h3>
                      <h3 class="project__title">{{project.price}} €</h3>
                    </div>
                  </a>
                </div>
              </div>
    {% endfor %}
    

    I assumed that by "main-image" you mean the first image of the project.

    single-project.html

    <h3 class="project__title">{{project.title}}</h3>
    <h3 class="project__title">{{project.price}} €</h3>
    <h3 class="singleProject__subtitle">Infos zum Produkt</h3>
    {{project.describtion}}
    {% for projectimage in project.projectimage_set.all %}
      <img src="{{projectimage.featured_images.url}}"/>
    {% endfor %}
    

    To avoid the N+1 query problem, you can also change the query in your view:

    views.py

    def projects(request):
        projects = Project.objects.all().prefetch_related('projectimage_set')
        context = {"projects":projects}
        return render(request, 'projects/projects.html', context)