Django とテーブル一覧の表示

記事
IT・テクノロジー

Django とテーブル一覧の表示

Django で SQL のデータベースのテーブルは「models.py」に Python のクラスを作ることで簡単に定義できました。実際のアプリケーションでは、テーブルにデータを保存して、そのデータの処理が必要です。

この記事では、簡単なデータベースのテーブルのアクセスについてまとめてみました。


テーブルのエントリーの名前は?

Django では、アプリのフォルダーの「models.py」に Python のクラスを作成して、そのクラスを「admin.py」に登録(register)すると、管理用アプリからアクセスできるようになります。

例えば、「Customer」というクラスを作成します。

class Customer(models.Model):
    name = models.CharField(max_length=50, help_text="The name of a customer.")
これを、「admin.py」に登録すると

from django.contrib import admin
from srd7.models import Customer
# Register your models here.
admin.site.register(Customer)
「127.0.0.1:8000/admin」にアクセスして、作成したスーパーユーザー(管理用のユーザー)でログインすると、このテーブルのデータの一覧の表示やデータの追加、修正、削除ができるようになります。

実際に顧客(カスタマ)を追加してみます。「add」をクリックして顧客名として「customerA」と入力して「SAVE」ボタンをクリックするとデータが追加されます。

ところが、一覧で表示される名前は、「Customer object (1)」のように表示されます。この名前をクリックすると、「Name」は、先ほど入力した「customerA」になっているので問題ではないのですが、少し不便です。

できれば、顧客名で一覧表示ができると便利ですよね?

そこで、クラスの定義のところに「str(self)」というメソッドを追加します。標準設定では、このメソッドがエントリーの名前として「Customer object (1)」を返すように設定されています。

class Customer(models.Model):
    name = models.CharField(max_length=50, help_text="The name of a customer.")

    def __str__(self):
       return self.name
のようにすると、エントリーの名前として、データベースの「name」フィールドを返すようになるので、一覧の表示の際も、顧客の名前で表示できるようになります。

テンプレートの利用

少し前の紹介した、完全に固定の内容(静的コンテンツ)の場合は、HTML を書けばその内容を Web ブラウザで表示させる事が可能です。しかし、データベースのテーブルの内容を表示する場合には、データが変わる可能性があります。

従って、データベースから取得した値に合わせて表示できると便利です。

もう一つは、Web サイトを作る際は、ページのヘッダーやフッターなどを統一したデザインにする事が多くなります。統一した記述を複数のページで使う場合は、テンプレートを作成して利用すると、デザインの変更にも対応しやすく便利です。

そこで、今回は、例として共通のフッターを利用するためのテンプレートを作成します。

プロジェクトのトップフォルダ(manage.py)があるフォルダに、「templates」というフォルダを作成します。同時に、「settings.py」を編集して、「TEMPLATES」の部分の記述を書き換えます。

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "templates")],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
「DIRS」に、プロジェクトフォルダの「templates」にテンプレートの HTML があることを Django に伝える記述を加えます。「APP_DIR」が「True」になっているので、アプリのフォルダにもテンプレートを置くことができる設定になっています。

まずは、全体のテンプレートとして、「basic.html」をプロジェクトフォルダに作成した「templates」の下に作成します。

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<div>
  {% block content %}
  {% endblock %}
<div class="footer">
    <footer>Copyright(c) 2021 by Silicon Valley Super Ware, all rights reserved.</footer>
</div>
</body>
</html>
例ではシンプルに、コピーライトを入れるだけです。「{% block content %}」と「{% endblock %}」の間にこのテンプレートを呼び出した、別のテンプレートの中身を挿入できます。このようにすると、全てのページに同じフッターにコピーライトを挿入できます。 必要に応じて、Bootstrap などの CDN リンクを「head」部分に入れておけば、Bootstrap のコンポーネントを利用できます。静的な CSS ファイルの呼び出しなどもこの部分で行うことができます。

一覧を表示するテンプレートは?

一覧を表示するテンプレートは、アプリのフォルダに作ることにします。 アプリの名前を「app」とすると、Django のトップレベルのフォルダに「app」というフォルダが、アプリを作成した際に作られていますので、そのフォルダ内に「templates/app」というフォルダを作ります。(templates というフォルダを作成した後に、その下に、app というフォルダを作成します)

これは、プロジェクトに複数のアプリが存在する場合、「template」だけだと、区別がつかないので、その下にアプリの名前と同じフォルダを作成するようになっているのが理由です。 この下にリストを表示するためのテンプレート「list.html」を作成します。

{% extends 'basic.html' %} {% block content %}
<div class="form-group">
  <table class="table table-hover">
    <thead>
      <tr class="table-primary">
        <th>{{ index }}</th>
        <th></th>
      </tr>
    </thead>
    <tbody>
      {% for item in lists %}
      <tr>
        <td>{{item.name}}</td>
        <td><button class="btn btn-primary">Select</button></td>
      </tr>
      {% endfor %}
    </tbody>
  </table>
</div>
{% endblock %}
Django のテンプレートは、いろいろなタグをサポートしていて、「{}」でテンプレートに埋め込むと、ループの処理や条件分岐なども使えますし、「{{ variable }}」で変数として埋め込む事ができます。

この機能を利用すると、データベースのデータのような動的なコンテンツも簡単に表示することができます。

あとは、表示するデータですが、これは「views.py」で作成してテンプレートに渡します。

表示データの準備

表示データは、アプリのフォルダの「views.py」で準備します。

import os
from django.conf import settings
from django.shortcuts import render
from .models import Customer
# Create your views here.

def list_customer(request):
    customers = Customer.objects.all()
    context = {
        'index': "Customer",
        'customers': customers
    }
    return render(request, 'app/list.html', context)
Customer のテーブルのエントリは、「Customer.objects.all()」で取得できます。 テンプレートに渡すデータは、ここでは「context」という JSON データを作成して渡します。例では、テーブルの見出しデータ(index)と顧客の配列(array)を渡しています。テンプレート側では、それぞれ、「index」と「customers」でアクセスできるようになります。

準備したデータをテンプレートに渡す部分は

「return render(request, 'app/list.html', context)」で指定します。 テンプレートのパスと、テンプレートに渡す JSON データを指定します。

URL のマッピング

データとテンプレートが準備できたら、最後は、表示する際に使う URL のマッピングをします。これは、プロジェクトレベルの「urls.py」で、アプリのフォルダの「urls.py」を指定しておいて、アプリの「urls.py」に必要なパスを追加して行います。

プロジェクトレベルの「urls.py」はプロジェクトフォルダにあります。

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('', include('app.urls')),
    path('admin/', admin.site.urls)
]
アプリレベルの「urls.py」はアプリのフォルダにあります。

from django.contrib import admin
from django.urls import path
from . import views

urlpatterns = [
    path('customers/',views.list_customer, name="list_customer"),
]
これで、開発用のサーバーでは、「127.0.0.1:8000/customers」にアクセスすると Customer に登録された顧客の名前の一覧が表示されるようになります。

選択できるようにボタンを HTML に入れてありますが、ボタンをクリックした場合の処理はこの例では省いてあります。

選択した顧客を Web サーバー側に送るには、Javascript でイベント処理をするか、HTML のフォームでサーバー側にポストする指定をすればサーバー側でデータを取得できます。

まとめ
Django ではバックエンドのデータ管理に SQL のデータベースを利用しています。データベースのアクセスをする場合でも、SQL を記述しなくても、Python のコードで全て処理が可能です。

この記事の例はシンプルな顧客の一覧をテーブルに表示するものですが、テンプレートの機能と、クラスで記述したテーブルのクラス経由のアクセスで動的に表示データを作って Web ブラウザーに送る例を紹介しました。

複雑なデータでもコンセプトは同じなので、データベースのデータの扱い方を覚えてしまえば、SQL を意識する事なく、データベースのデータを活用できるようになるのは大きな魅力です。

サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す