#今回使用するのはDetailView
目標はListViewで表示されるデータの詳細を見れるようにすることです。
前回のIndexView作成チュートリアルの続きの内容になります。
超絶シンプルに書いており、djangoに慣れようという目的が強いため、手を動かしてDetailViewに慣れたいといった方向けに記事を書いています。
また、初めからTemplateViewを練習したい方は初めのIndexView作成チュートリアルからご覧になると、確実に作成ができます。
##ファイル構成
mysite
│ db.sqlite3
│ manage.py
├─mysite
│ │ settings.py
│ │ urls.py
└─test_app
│ admin.py
│ apps.py
│ models.py
│ tests.py
│ urls.py(ここをルーティング設定のために編集)
│ views.py(ここをDetailView設定のために編集)
├─migrations
└─templates
└─test_app
└─list.html(ここを詳細ページに飛ぶために編集)
detail.html(ここをページ表示のために編集)
##前回作成したShopモデルを使用します。
使用するモデル名はShop
です。
nameは30文字制限の文字列フィールド、
tell_numは13文字制限の文字列フィールド、
addressは30文字制限の文字列フィールド、
created_atは作成日と時間が初期値に設定される日時フィールドを定義しています。
from django.db import models
# Create your models here.
class Shop(models.Model):
#各フィールドの定義
name = models.CharField('shopname',max_length=30)
tell_num = models.CharField('tell_number',max_length=13)
address = models.CharField('address',max_length=30)
created_at = models.DateTimeField(auto_now_add=True)
#admin画面の表示内容
def __str__(self):
return self.name
##数字で詳細を表示するためにルーティングを設定する
ここではhttp://local:8000/1/
など、数字を入れるだけで紐づく詳細ページにアクセスできるように設定します。
このようなpath
を書いてあげます。
from django.urls import path
from . import views
app_name = 'test_app'
urlpatterns = [
path('index/',views.IndexView.as_view(),name='index'),
path('<int:pk>/',views.DetailView.as_view(),name='detail'),
]
int型のpkという数字が入るところを用意します。views.py
のDetailView
をas_view()
でビューとして設定しています。パスの名前はdetail
とし、htmlファイルからurl
を指定する場合はdetail
と指定できるようにします。わかりやすいname
にしてあげると使いやすいですね。
##views.pyでDetailViewを設定
from django.views import generic
from .models import Shop
class IndexView(generic.ListView):
model = Shop
template_name = 'test_app/list.html'
#ここを追加
class DetailView(generic.DetailView):
model=Shop
template_name = 'test_app/detail.view'
djangoで用意されているgenericライブラリの中のDetailViewを継承しています。
モデルとテンプレートの指定のみで設定完了です。
##detail.htmlで詳細ページを作成
templates/test_app/detail.htmlを新たに作成します。
ファイル名はビューファイルでtemplate_name
として指定されています。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>{{ shop.name }}の詳細</p>
<table>
<tr>
<th>店名</th>
<th>電話番号</th>
<th>住所</th>
<th>ページ作成日</th>
</tr>
<tr>
<td>{{ shop.name }}</td>
<td>{{ shop.tell_num }}</td>
<td>{{ shop.address }}</td>
<td>{{ shop.created_at }}</td>
</tr>
</table>
</body>
</html>
shop.といった形式でモデルで定義した項目を{{ }}でくくり指定すると、html側で表示がなされます。
DetailViewを用いるとモデル名にそって先頭が小文字となったものを指定できます。
自動でこれまた設定してくれているので、モデルデータの指定が楽です!
例えば、モデル名をShop
とすると、shop.
と指定することになります。Carだとcarですね!
##リスト表示のindexページに詳細リンクを張ります。
このファイルでShopモデルのデータを表形式で表示しています。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>一覧の表示</p>
<table>
<tr>
</tr>
{% for shop in shop_list %}
<tr>
<td>{{ shop.name }}</td>
<td><a href="{% url 'test_app:detail' shop.pk %}">詳細</a></td>
</tr>
{% endfor %}
</table>
</body>
</html>
<a href="{% url 'test_app:detail' shop.pk %}">詳細</a>
が難しいのですが、htmlのa
グで、リンク先をurls.pyのapp_name
で指定したtest_app
のname
がdetail
であるpath
と、shop
のpk
とあわせて記述されています。
ここではshop.idとしてもかまいません。
これで、詳細をクリックできるリンクが作成できました。
##ページの動作確認
サーバーを起動し
$python manage.py runserver
indexページを指定すると
http://localhost:8000/index
そこで、詳細をクリックすると。
http://localhost:8000/1
完成です!
##うまく動かない方へ「error:Generic detail view DetailView must be called with either an object pk or a slug in the URLconf.」
Generic detail view DetailView must be called with either an object pk or a slug in the URLconf.
が出てしまう場合、pkをurls.pyに用いないといけませんので、注意しましょう。<int:pk>
とpk
以外受け付けません。
ビューを呼び出す場合、pkという変数名の決まりでモデル指定中のShopモデルから該当オブジェクトを呼び出すのです。例えば、タピオカ屋をクリックすると、データのprimary keyが1のデータの詳細がdetai.htmlのルールに沿って表示がなされます。
#最後に
このように、テンプレートビューであるDetailビューなどを用いる場合、ルールがとても多いため混乱する恐れが高いです。💦
指定されたように書かないと動かないことが多いため、サンプルを見てたくさん書いてみると、書き方に慣れてきます。
やはり、自分で好みのサイトを全く同じでもいいので作ってみると勉強になりますよ!