ジャンゴ(django)のビュー(View)

2019-06-03

ウェブページのためジャンゴ(django)のビュー(View)を使う方法について説明します。

概要

今までデーターを保存するデーターベースとの連動やデーターを生成して読んで更新して削除(CRUD - Create Read Update Delete)する方法、そしてユーザーが接続するURLを生成する方法などジャンゴ(django)でウェブサービスをするための色んなことを見てみました。今回のブログではユーザーに見せるウェブページを作るためジャンゴ(django)のビュー(View)を使う方法について見てみます。

このブログはシリーズです。下記のリンクでシリーズの他の記事を見ることができます。

また、このブログシリーズで説明したソースコードはgithubに公開されております。下記のリンクで確認できます。

URL確認

以前のブログ(ジャンゴ(django)のルーティング(Routing))で私たちはユーザーが接続するURLと静的HTMLを連結する方法についてみてみました。下記のジャンゴ(django)コマンドを実行してテストサーバーを起動した後、http://127.0.0.1:8000/に接続するとHello Worldが表示されるウェブページを確認することができます。

# source venv/bin/activate
# cd django_exercise/
python manage.py runserver

データー伝達

以前のブログ(ジャンゴ(django)のORM)で生成したデーターをウェブページで見せるためビュー(View)にデーターを伝達してみます。blog/views.pyファイルを開いて下記のように修正します。

from django.shortcuts import render
from .models import Post

def posts(request):
    posts = Post.objects.filter(published_at__isnull=False).order_by('-published_at')
    return render(request, 'blog/posts.html', {'posts': posts})
  • from .models import Post: 私たちが作ったPostモデル(Models)を読んできます。
  • posts = Post.objects.filter(published_at__isnull=False).order_by('-published_at')
    • published_at__isnull=False: published_atフィールドがnullじゃない場合(__isnull=False)のデーターを持ってきます。
    • order_by('-published_at'): データーをpublished_atフィールドで降順でソーティングします。
  • return render(request, 'blog/posts.html', {'posts': posts}): 持ってきたデーターをblog/posts.htmlページに{'posts': posts}でposts変数で送ります。

データー表示

上で伝達したデーターを画面に表示する方法についてみてみましょう。blog/templates/blog/posts.htmlを開いて下記のように修正します。


<html>
  <head><title>Hello World</title></head>
  <body>
    {% for post in posts %}
    <div>
      <h1>
        {{ post.title }}<small>(published: {{ post.published_at }})</small>
      </h1>
      <p>{{ post.content | linebreaksbr }}</p>
    </div>
    {% endfor %}
  </body>
</html>

  • {% for post in posts %}...{% endfor %}: 上でblog/views.pyに伝達したpostsデーターリストからpostでデーターを一つずつ持てくるループです。
  • {{ post.title }}<small>(published: {{ post.published_at }})</small>: postデーターのtitle / published_atフィールドを表示します。 데이터를 표시합니다.
  • <p>{{ post.content | linebreaksbr }}</p>: postデーターのcontentを持って来て改行(\n)を改行タグ(<br/>)に変換して表示します。

上のようにコードを修正してhttp://127.0.0.1:8000/に接続すると下記のようにデーターが表示されることが確認できます。

ジャンゴ(django)のビュー(View)を使ってデーター表示

もっと練習するため、詳細ページを作ってみましょう。上で作ったblog/templates/blog/posts.htmlを下記のように修正します。


<html>
  <head><title>Hello World</title></head>
  <body>
    {% for post in posts %}
    <a href="{% url 'post_detail' id=post.id %}"> <!-- <<<<<<<<<<<<<<<<<<<<< here -->
      <h1>
        {{ post.title }}<small>(published: {{ post.published_at }})</small>
      </h1>
      <p>{{ post.content | linebreaksbr }}</p>
    </a> <!-- <<<<<<<<<<<<<<<<<<<<< here -->
    {% endfor %}
  </body>
</html>

  • {% url 'post_detail' id=post.id %}: 私たちが定義したdjango_exercise/urls.pyblog/urls.pypost_detailの名前(name)を探して当該URLで変換します。この時idと言うパラメーターを作ってPostのidを入れます。

まだ、post_detailとマッチングされるURLを作ってないです。今からpost_detailを対応するURLとビュー(View)を作ってみましょう。blog/templates/blog/post_detail.htmlを作って下記のように修正します。


<html>
  <head><title>Hello World</title></head>
  <body>
    <a href="{% url 'posts' %}">
      Post List
    </a>
    <h1>
      {{ post.title }}
    </h1>
    <p>created: {{ post.created_at }}</p>
    <p>updated: {{ post.updated_at }}</p>
    <p>published: {{ post.published_at }}</p>
    <p>author: {{ post.author.username }}</p>
    <p>{{ post.content | linebreaksbr }}</p>
  </body>
</html>

  • {% url 'posts' %}: URLファイルでpostsと言う名前(name)を持ってるURLを探してそのURLで変換します。
  • author: {{ post.author.username }}: 私たちが作ったPostモデルとジャンゴ(django)が基本的提供してるauth.Userと連結して作者(author)フィールドを作りました。このように連携してるモデル(Models)からusernameを持って来て表示することもできます。

画面に表示するページが準備できました。blog/urls.pyを開いて下記のように修正します。

from django.urls import path
from . import views

urlpatterns = [
    path('', views.posts, name='posts'),
    path('post/<int:id>/', views.post_detail, name='post_detail'), # <<<<<<<<<<<< here
]
  • post/<int:id>/: URLにパラメーターで来た数字のデーターであるidを表示します。
  • name='post_detail': URLの名前はpost_detailで、views.post_detailとマッピングされています。

これで{% url 'post_detail' id=post.id %}を使ったらpost/<int:id>/のURLを表示してviews.post_detailとマッピングする準備が終わりました。blog/views.pyファイルを開いて下記のように修正します。

from django.shortcuts import render, get_object_or_404 # <<<<<<<<<<<< here
from .models import Post


def posts(request):
    posts = Post.objects.filter(
        published_at__isnull=False).order_by('-published_at')
    return render(request, 'blog/posts.html', {'posts': posts})

# <<<<<<<<<<<< here
def post_detail(request, id):
    post = get_object_or_404(Post, id=id)
    return render(request, 'blog/post_detail.html', {'post': post})
  • get_object_or_404: ジャンゴが基本的提供するファンクションを追加します。このファンクションは当該オブジェクト(Object)からデーターを持って来るがデーターがない場合404エラーを発生するファンクションです。
  • def post_detail(request, id):: 新しく追加したURLとマッピングするファンクションです。パラメーターで渡したidを別の変数でもらえます。

これで詳細ページを作ってみました。http://127.0.0.1:8000に接続したら以前と違って下記のようにリンクがあるページが見えます。

ジャンゴ(django)のモデル(Models)の詳細ページリンク

当該リンクを押したら詳細ページURL(http://127.0.0.1:8000/post/2/)に移動して下記のようにPostの詳細ページが見えます。

ジャンゴ(django)のモデル(Models)の詳細ページ

テンプレートファイル

ビュー(View)とURL、そしてデーターを表示する方法にはちょっと慣れた気がします。しかし、HTMLファイルに重複するコードがたくさん見えます。まだ、css, jsmetaタグがないから大丈夫ですが、このタグがドンドン多くなったら重複するコードが増えます。このような重複部分を新しファイルで作って持って来る方法についてみてみます。

一旦、静的ファイル(css, js 등)を追加する方法についてみてみます。blog/static/css/main.cssファイルを生成して下記のように修正します。

h1 {
  color: red;
}

このブログではデザインの部分は説明しません。もっと美しくウェブページを作りたい方はこのファイルを修正してください。ジャンゴ(django)はstaticと言う名前のフォルダを自動に探して登録するので追加的登録作業をする必要はありません。

じゃblog/templates/blog/layout.htmlファイルを作って下記のように修正します。


{% load static %}
<html>
  <head>
    <title>Hello World</title>
    <link rel="stylesheet" href="{% static 'css/main.css' %}" />
  </head>
  <body>
    {% block content %} {% endblock %}
  </body>
</html>

  • {% load static %}: このファイルからstaticフォルダを使えようにstaticフォルダを読んで来ます。
  • <link rel="stylesheet" href="{% static 'css/main.css' %}" />: 私たちが読んできたstaticフォルダからcss/main.cssを探してそのURLに変換します。
  • {% block content %} {% endblock %}: このレイアウト(layout)ファイルに必要なデーター(content)を表示する位置を設定します。このように表示したい部分をblock [name]で設定してそのブロック(block)を変換する部分を[name]を使って作ります。

レイアウト(layout)ファイルを使うためblog/templates/blog/posts.htmlファイルを開いて下記のように修正します。


{% extends 'blog/layout.html' %}

{% block content %}
  {% for post in posts %}
    <a href="{% url 'post_detail' id=post.id %}">
      <h1>
        {{ post.title }}<small>(published: {{ post.published_at }})</small>
      </h1>
      <p>{{ post.content | linebreaksbr }}</p>
    </a>
  {% endfor %}
{% endblock %}

  • {% extends 'blog/layout.html' %}: このファイル(posts.html)は私たちが作ったレイアウト(layout.html)ファイルを使います。
  • {% block content %}...{% endblock %}: 私たちがレイアウト(layout.html)ファイルに作ったブロック(block)、そこで名前がcontentであるブロック(block)をここで作成した内容で変換します。

そしてblog/templates/blog/post_detail.htmlファイルを開いて下記のように修正します。


{% extends 'blog/layout.html' %}

{% block content %}
  {% for post in posts %}
    <a href="{% url 'post_detail' id=post.id %}">
      <h1>
        {{ post.title }}<small>(published: {{ post.published_at }})</small>
      </h1>
      <p>{{ post.content | linebreaksbr }}</p>
    </a>
  {% endfor %}
{% endblock %}

上で説明した内容と同じようにレイアウト(layout.html)ファイルを使って名前がcontentであるブロック(block)をここで作成した内容で変換します。

確認

今まで作成した内容を確認するためhttp://127.0.0.1:8000/に接続してみます。そしたら私たちが作成したcssが適用された画面が下記のように見えます。(画面が上手く表示できない方はテストサーバーを再起動してください。)

ジャンゴ(django)のテンプレート活用 - メインページ

リンクを押して詳細ページ(http://127.0.0.1:8000/post/2/)に移動しても下記のようにcssが適用されたことが確認できます。

ジャンゴ(django)のテンプレート活用 - 詳細ページ

これで私たちはジャンゴ(django)のテンプレートを活用して静的ファイル(css, jsなど)を持って来る方法とHTMLの重複を減らすための方法についてみてみました。

完了

今回のブログでジャンゴ(django)のビュー(View)を使う全般的方法についてみてみました。データーを持って来て画面に表示して、表示される画面を管理するためのジャンゴ(django)のテンプレートを確認してみました。また、cssとjsような静的ファイル(static)を持って来る方法もみてみました。もう、私たちはこれを使って一般的なウェブサービスサイトを作れるようになりました!

Buy me a coffeeBuy me a coffee
Posts