#はじめに
最近個人的にアプリケーション開発していて一つ詰まった箇所として、models.pyで作成したモデルをtemplatesに表示させることがありました。多対多のリレーショナルデータベースのモデルの作成に関する解説は多く見かけ参考にさせていただきましたが、それをhtmlファイルに表示する方法に関する情報がどうしてもDjango初心者の自分には分かりにくく、理解に時間がかかりました。今回はDjangoの初心者の方でも分かりやすく、一つの簡易アプリケーションを開発しながら多対多関係モデルの作成、表示方法について解説していきたいと思います。
##今回作成する簡易アプリについて
今回のテーマとして多対多関係モデルを扱いますので、まずはモデルを作る前にどのようなアプリを作るか書いていきます。分かりやすい例としてパッと出てきたものが動物園(上野動物園、旭川動物園など)のリンクを押すとその動物園にいる動物(象、キリン、アルパカなど)を表示してくれるアプリケーションだったので、簡易的なものになりますが、そのようなアプリを作っていきたいと思います。
##多対多関係モデルとは
Djangoにおける多対多関係モデルとはリレーショナルデータベースにおいて多対多のリレーション(関係)をもつモデルのことです。もう少し噛み砕いて説明するため、今回作成するアプリケーションを例にして説明します。
下の図のように動物園は様々な種類の動物を管理しています。図を用いて説明すると一つの動物園は同時に何種類の動物と繋がっています。また動物に関しても同じことが言え、例えば象を見てみると動物園Aと動物園Bにいます。このように、お互い(今回の場合だと動物園、動物)が一つのオブジェクトではなく複数のオブジェクトに存在している場合、モデル同士が多対多の関係にあると言えます。
(補足情報)
Djangoはデータベースとしてリレーショナルデータベースを採用しています。リレーショナルデータベースとは自身とは異なるテーブルのカラムを参照して、自身のテーブルのカラムとして関連付けができるデータベースです。
##モデルを作成する前に
DBモデルを作成する前にアプリケーションとして最低限の機能を果たせるよう、settings.pyの設定、urlの繋ぎこみとviewsの記述を軽くやっておきたいと思います。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app_name', #startappでつけたアプリ名を入れる
]
urls.pyも今回は要らないがprojectのurl --> appのurl --> htmlファイルの形を作る。
from django.urls import include
urlpatterns = [
path('', include('app_name.urls')),
]
from django.urls import path
from .views import displayfunc
urlpatterns = [
path('', displayfunc),
]
urls.pyの繋ぎこみを確かめるためにviewsも記述しておきます。
from django.shortcuts import render
def displayfunc(request):
return render(request, 'home.html')
templatesフォルダを作成しhome.htmlをその下に作り、適当な単語(自分はDisplayと入れときました)を入れ、runserverしてみましょう。
このように表示されれば、繋ぎこみが成功と分かりますね!では早速モデルを作っていきましょう!
##モデルの作成、データの入力
多対多関係モデルをDjangoにおいて作るにはManyToManyFieldを使います。使い方としては参照したいモデルをManyToManyFieldsに渡してあげることで参照したカラムを作ることができます。下のコードを見ると分かりやすいかと思います。
from django.db import models
class Animal(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Zoo(models.Model):
name = models.CharField(max_length=100)
keeping = models.ManyToManyField(Animal) #Animalを渡す
def __str__(self):
return self.name
これでモデルは完成しましたので次はこのモデルにデータを入れていきたいと思います。いきなりadminページでデータを入力するのではなくDjango shellでテストしてからadminページに行く形が一般的なので今回もそのようにしていきます。以下のコードでDjangoからshellコマンドが打てるようになります。
$ python manage.py shell
まずはmodels.pyのモデルをターミナル上で扱うためにインポートしていきます。
次に二つのモデルにデータを追加していきます。
>>> from app_name.models import *
>>> a1 = Animal.objects.create(name="elephant")
>>> z1 = Zoo.objects.create(name="Ueno Zoo")
次に二つのモデルの関連付けを行います。
>>> a1 = Animal.objects.get(name="elephant")
>>> z1 = Zoo.objects.get(name="Ueno Zoo")
>>> z1.keeping.add(a1)
関連付けが上手くいっているか確認。上手く表示されれば成功です!
>>> z1.keeping.all()
##htmlファイルにデータを表示する
それではmodels.pyのデータを表示させていきましょう。ここのパートはコードを載せた方が分かりやすいかと思うので載せていきます。まずはviewsを書き換えます。
from .models import Zoo
def displayfunc(request):
object = Zoo.objects.all()
return render(request, 'home.html', {'object': object})
def detailfunc(request, pk):
zoo = Zoo.objects.get(pk=pk)
return render(request, 'detail.html', {'zoo': zoo})
続いてurlsで繋ぎこみをしていきます。あとで使うのでnameも設定。
path('detail/<int:pk>', detailfunc, name="detail") #追加する
最後にhtmlファイルです。
<body>
{% for zoo in object %}
<p><a href="{% url 'detail' zoo.pk %}">{{ zoo.name }}</a></p>
{% endfor %}
</body>
<body>
{% for animal in zoo.keeping.all %}
<p>{{ animal }}</p>
{% endfor %}
</body>
これで完成です!runserverして確認してみましょう。
例えば動物園 'Ueno Zoo'をクリックすると
このように動物園にいる動物が(装飾もなしで非常にお粗末なWebページですが)動きます。今回のテーマとしては多対多関係モデルを扱うことですので、これ以上のデータの追加やCSSなどの装飾はしません。とりあえずはアプリは完成です!
##最後に
読んでくださった方はありがとうございます!
もし何かしらのミス、誤りがあれば連絡お願いいたします。