商品リスト画面を作成します。

モデル

Itemモデルを追加します。

内容は、タイトル、値段、カテゴリ、スラッグ、説明、画像です。

app/models.py

from django.db import models


class Item(models.Model):
    title = models.CharField(max_length=100)
    price = models.IntegerField()
    category = models.CharField(max_length=100)
    slug = models.SlugField()
    description = models.TextField()
    image = models.ImageField(upload_to='images')

    def __str__(self):
        return self.title

コード解説

画像のアップロード先は、settings.py で設定したMEDAI_URLmediaフォルダになります。

image = models.ImageField(upload_to='images')

スラッグとは?

スラッグは文字、ハイフン、数字、アンダースコアだけを含んだ文字列です。

SlugFieldフィールドを使用して、URL の一部になります。

スラッグを使用しないと、商品詳細画面の URL は下記のようになります。

スラッグを使用すると、下記のように商品ごとに割り当てた URL を使用することができます。

slug = models.SlugField()

Admin

管理画面で操作できるように設定します。

app/admin.py

from django.contrib import admin
from .models import Item

admin.site.register(Item)

マイグレーション実行

モデルを追加したので、マイグレーションが必要になります。

(myvenv) ~$ python3 manage.py makemigrations
(myvenv) ~$ python3 manage.py migrate

管理画面

管理画面で商品リストを登録します。

複数個商品を登録しておくと、レイアウトがしやすくなります。

私は家電を 8 個登録しました。

管理画面

URL

URL を設定します。

商品リストはトップページで表示します。

app/urls.py

from django.urls import path
from app import views

urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
]

ビュー

商品リストのビューを作成します。

app/views.py

from django.shortcuts import render
from django.views.generic import View
from .models import Item


class IndexView(View):
    def get(self, request, *args, **kwargs):
        item_data = Item.objects.all()
        return render(request, 'app/index.html', {
            'item_data': item_data
        })

テンプレート

base

ベースのテンプレートを作成します。

Bootstrap を使用してレイアウトをしています。

app/templates/app/base.html

{% load static %}

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
    />
    <link rel="stylesheet" href="{% static 'css/style.css' %}" />
    <title>ECサイト</title>
  </head>

  <body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
      <div class="container">
        <a class="navbar-brand" href="/">ECサイト</a>
        <ul class="navbar-nav ml-auto">
          <li class="nav-item">
            <a class="nav-link" href="/">ホーム</a>
          </li>
          {% if user.is_authenticated %}
          <li class="nav-item">
            <a class="nav-link" href="{% url 'profile' %}">プロフィール</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="{% url 'account_logout' %}">ログアウト</a>
          </li>
          {% else %}
          <li class="nav-item">
            <a class="nav-link" href="{% url 'account_signup' %}"
              >サインアップ</a
            >
          </li>
          <li class="nav-item">
            <a class="nav-link" href="{% url 'account_login' %}">ログイン</a>
          </li>
          {% endif %}
        </ul>
      </div>
    </nav>

    <main>
      <div class="container">{% block content %} {% endblock %}</div>
    </main>

    <footer class="py-2 bg-dark">
      <p class="m-0 text-center text-white">
        Copyright &copy; Django Startup 2020
      </p>
    </footer>

    {% block extra_js %} {% endblock %}
  </body>
</html>

コード解説

一部の画面のみ JavaScript を使用したいので、JavaScript 用のブロックを設定しておきます。

{% block extra_js %} {% endblock %}

index

商品リストのテンプレートを作成します。

app/templates/app/index.html

{% extends "app/base.html" %} {% block content %}

<div class="text-center my-5">
  <div class="row">
    {% for item in item_data %}
    <div class="col-lg-3 col-md-6">
      <div class="card img-thumbnail itemlist mb-3">
        <img class="card-img-top card-thum" src="{{ item.image.url }}" alt="" />
        <div class="card-body text-center px-2 py-3">
          <p class="mb-0 text-secondary">{{ item.category }}</p>
          <h5 class="font-weight-bold">{{ item.title }}</h5>
          <h4 class="font-weight-bold">{{ item.price }}円</h4>
        </div>
        <a class="stretched-link" href=""></a>
      </div>
    </div>
    {% endfor %}
  </div>
</div>
{% endblock %}

コード解説

item_dataで商品を取得できます。

{% for item in item_data %}

stretched-linkクラスでdivタグで囲われている全体がリンクになります。

<a class="stretched-link" href=""></a>

CSS

CSS で商品リストを装飾します。

app/static/css/style.css

/* base */

body {
  background: #f1f1f1;
  display: flex;
  flex-flow: column;
  min-height: 100vh;
}

main {
  flex: 1;
}

/* index */

.itemlist img {
  height: 150px;
  object-fit: contain;
}

確認

商品リスト画面が表示されることを確認します。

http://127.0.0.1:8000/

商品リスト