Django — Step 12

Item pages

Brian Mayrose
5 min readJul 23, 2019

This is a continuation from step 11

Now that our Django application is displaying the items in the database, we should make the listed items link to a page that will give all the details specific to the item chosen.

First, in the display_1/index.html page, below the {{ i.description_1 }} tag
let’s start by creating a ‘More Info’ link:

<a href="{% url 'display_1_item1' i.id %}" class="btn btn-primary btn-block">More Info</a>

This link passes the i.id object to the path with the name display_1_item1 found in the display_1/urls.py file:

path('<int:item_id>', views.display_1_item, name= 'display_1_item1'),

the path function creates a path based on the id number while passing the i.id object to the view function called display_1_item found in display_1/views.py:

def display_1_item(request, item_id):
i = get_object_or_404(item, pk=item_id)
context = { 'i': i }
return render(request, 'display_1/display_1_item.html', context)

Besides request, the view function will also receive the item_id variable as an argument. item_id was defined in the path function in urls.py: <int:item_id>

The first line of the display_1_item view function defines what to do with the i.id variable that was passed from the ‘More Info’ link and is used in the for loop, {% for i in dbitems %}, in the display_1/index.html template.

We set i to get_object_or_404(item, pk=item_id). We also need to import the get_object_or_404() function from django.shortcuts at the top of views.py:

from django.shortcuts import render, get_object_or_404

The get_object_or_404() function receives two arguments. The first, item, is the name of the database model from display_1/models.py. The second argument is pk=item_id. PK is the lookup parameters, we set it to item_id to keep it dynamic. If we were to use a number like 2 instead of the variable Django will only show item 2 when clicking on the ‘More Info’ link any item

Then we add the i object to the context definition and render function:

context = { 'i': i }
return render(request, 'display_1/display_1_item.html', context)

Save the views.py file and create a new template in the templates/display_1 directory called display_1_item.html

Inside display_1_item.html put this markup:

{% extends 'base.html' %}
{% block title %} | {{ i.title }} {% endblock %}
{% block content %}
<section>
<div class="container text-center">
<div class="box_1">
<img class="card-img-top" src="{{ i.photo_main.url }}" alt="">
{% if i.photo_1 %}
<img class="card-img-top" src="{{ i.photo_1.url }}" alt="">
{% endif %}
{% if i.photo_2 %}
<img class="card-img-top" src="{{ i.photo_1.url }}" alt="">
{% endif %}
{% if i.photo_3 %}
<img class="card-img-top" src="{{ i.photo_1.url }}" alt="">
{% endif %}
{% if i.photo_4 %}
<img class="card-img-top" src="{{ i.photo_1.url }}" alt="">
{% endif %}
{% if i.photo_5 %}
<img class="card-img-top" src="{{ i.photo_1.url }}" alt="">
{% endif %}
{% if i.photo_6 %}
<img class="card-img-top" src="{{ i.photo_1.url }}" alt="">
{% endif %}
<h2>{{ i.title }}</h2>

<p>{{ i.description_1 }}</p>
{% if i.description_2 %}
<p>{{ i.description_2 }}</p>
{% endif %}
{% if i.description_3 %}
<p>{{ i.description_3 }}</p>
{% endif %}
{% if i.reference_link %}
<a href="{{ i.reference_link }}" class="btn btn-primary btn-block">Reference Link</a>
{% endif %}
<p>{{ i.list_date }}</p>
</div>
</div>
</section>
{% endblock %}

We first extend the base.html. Then using the same classes as the index.html page we create a section and container/box divs.

Because we passed the i object through the view we do not need to create a for loop in this template, we can just go ahead and use the object. we can call the main image first:

<img class="card-img-top" src="{{ i.photo_main.url }}" alt="">

Following this, we can use our database model as a reference and create Jinja if statements to check if more photos are available:

{% if i.photo_1 %}
<img class=”card-img-top” src=”{{ i.photo_1.url }}” alt=””>
{% endif %}

We do this for all 6 of the remaining available photos. If we did not use the if statement and there were no photo_1 available Django will give an error. We need to use this format for any object in the database that has blank set to true:

description_1 = models.TextField(blank=True)

We do the same for the optional descriptions:

{% if i.description_2 %}
<p>{{ i.description_2 }}</p>
{% endif %}

Save display_1_item.html and start your server. Navigate to the display_1 page called Galler1 in the navigation bar and you will see the new ‘More Info’ buttons:

Test out the ‘More Info’ button by clicking it. It will take you to the item description page we created:

If you go into the admin panel of your project and add more descriptions and add more images they will be displayed on this page:

I added some super simple styling:

<div class="container text-center">
<div class="box_1">
<img class="card-img-top" src="{{ i.photo_main.url }}" alt="">
</div>
<div class="box_1">
{% if i.photo_1 %}
<img class="card-img-top" src="{{ i.photo_1.url }}" alt="">
{% endif %}</div>
<div class="box_1">
{% if i.photo_2 %}
<img class="card-img-top" src="{{ i.photo_2.url }}" alt="">
{% endif %}</div>
<div class="box_1">
{% if i.photo_3 %}
<img class="card-img-top" src="{{ i.photo_3.url }}" alt="">
{% endif %}</div>
<div class="box_1">
{% if i.photo_4 %}
<img class="card-img-top" src="{{ i.photo_4.url }}" alt="">
{% endif %}</div>
<div class="box_1">
{% if i.photo_5 %}
<img class="card-img-top" src="{{ i.photo_5.url }}" alt="">
{% endif %}</div>
<div class="box_1">
{% if i.photo_6 %}
<img class="card-img-top" src="{{ i.photo_6.url }}" alt="">
{% endif %}</div>
<div class="box_1"><h2>{{ i.title }}</h2><p>{{ i.description_1 }}</p>
{% if i.description_2 %}
<p>{{ i.description_2 }}</p>
{% endif %}
{% if i.description_3 %}
<p>{{ i.description_3 }}</p>
{% endif %}
{% if i.reference_link %}
<a href="{{ i.reference_link }}" class="btn btn-primary btn-block">Reference Link</a>
{% endif %}
<p>{{ i.list_date }}</p>
</div>
</div>

In the next step we will cover posting data to the database using Django Forms:

--

--