サイドバーの「Django ドキュメント検索」というプレースホルダの入った検索では、Django ドキュメント (Django 2.1) の公式サイト内を検索できます
Django チュートリアルの進め方 その 3 (1)

目次

はじめに

Django を学習するには、何はともあれ公式チュートリアル「はじめての Django アプリ作成」からスタートしてみるのが良いでしょう。しかし、いざチュートリアル通りに進めようとしても躓く場合も多いと思います。そこで、「チュートリアルの進め方」シリーズとして、チュートリアルに沿った作業を行いながら補足事項をまとめることにしました。チュートリアルで躓いた際のヒントとしてお使いください。

利用環境は Ubuntu、 Linux Mint を中心として説明しますが、 Windows についても補足します。

前回は、Django チュートリアルの進め方 その 2 (3) と題してはじめての Django アプリ作成、その 2 の後半についてまとめました。

今回は、はじめての Django アプリ作成、その 3 の前半についてまとめました。

オーバービュー

Django のビューは MVC で言うところの C = Controller に近い概念です。ビューは、テンプレート (MVC で言うところの V = View はこちらに近い) を利用して画面を描画します。 polls アプリケーションでは、下記のようなビューを作成します。

質問 "インデックス" ページ -- 最新の質問をいくつか表示


質問 "詳細" ページ -- 結果を表示せず、質問テキストと投票フォームを表示


質問 "結果" ページ -- 特定の質問の結果を表示


投票アクション -- 特定の質問の選択を投票として受付

※画面なし。処理のみ。

もっとビューを書いてみる

まず、detail, results, vote という 3 つのビューを追加します。ここで定義するのは、動作確認するための仮の処理(スタブ)です。

from django.http import HttpResponse


def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")


def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)


def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)


def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

各ビューは HttpResponse を返します。

次に、上記ビューに URL から到達するための経路を URLconf で定義します。

from django.urls import path

from . import views

urlpatterns = [
    # ex: /polls/
    path('', views.index, name='index'),
    # ex: /polls/5/
    path('<int:question_id>/', views.detail, name='detail'),
    # ex: /polls/5/results/
    path('<int:question_id>/results/', views.results, name='results'),
    # ex: /polls/5/vote/
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

ブラウザで http://127.0.0.1:8000/polls/34/ にアクセスしてみます。 (Python manage.py runserver を実行しておいてください。)

URL で指定した 34 が反映されたメッセージになっています。

まず、URL の /polls/34/ の先頭部分 polls/ は、 mysite.urls  で定義された path('polls/', include('polls.urls')) の定義により、以降の解析は polls.urls に委託されます。

次に 34/ の部分は、polls.urls で定義された path('<int:question_id>/', views.detail, ...) に合致するため polls.views.detail ビューが呼ばれます。その際に <int:question_id> の定義により、34 が question_id というキーワード変数としてビューに渡されます。detail ビューは  question_id を受け取り、 HttpResponse に渡す文字列に値を反映させています。

実際に動作するビューを書く

最新の 5 件の質問項目をカンマ区切り、日付順で表示するように index ビューを修正します。

from django.http import HttpResponse

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    output = ', '.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)
.
.
.

objects で取得できる Manager は、 QuerySet のメソッドを直接実行できます。

order_by( フィールド名 ) はソートを指定するメソッドです。フィールド名の先頭に '-' を付加することで逆順 (降順) を指定します。

order_by()

fields で指定したフィールドで並べ替えます。デフォルトは昇順で、降順にしたい場合はフィールド名の前に '-' を付加します。下記のように、複数のフィールドを指定する事もできます。

Entry.objects.order_by('-pub_date', 'headline')

この場合は、'pub_date' フィールドの内容で降順にソートした跡、'headline' フィールドで昇順にソートします。

動作を確認します。ブラウザで http://127.0.0.1:8000/polls/ にアクセスしてみます。

まだ一つしか質問事項が無いので、表示される質問は一つだけです。

ページデザインはテンプレートに記述すべき内容ですので、 ページデザインの記述をテンプレートへ移してゆきます。
polls/templates/polls/index.html を作成します。ディレクトリ構造は下記のようになります。

 

polls
├── __init__.py
├── __pycache__
├── admin.py
├── apps.py
├── migrations
├── models.py
├── templates
│   └── polls
│       └── index.html
├── tests.py
├── urls.py
└── views.py

polls/templates の下にもう一つ polls ディレクトリを作成するのがわかりにくいかもしれません。

テンプレートの配置
Django で使用するテンプレートは、各アプリケーションの templates ディレクトリの下にあるテンプレートから探索されます。
一つの Djanogo プロジェクトは複数のアプリケーションを有しますので、複数のアプリケーションで index.html というテンプレートを定義していた場合、それらを区別する方法がなくなってしまいます。
そのため、アプリケーション名のディレクトリを templates ディレクトリ内に作成し、その下にテンプレートを配置する習慣になっています。(テンプレートの配置方法については、別の方法もありますがここでは触れません)

テンプレート内容は、チュートリアルのコードのままです。

{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

制御文などは {% タグ %} という書き方で実現できます。タグとしては、 for / endfor,  if / else / endif 等が利用できます。また、 {{ 変数名 }} として変数を利用できます。

latest_question_list は、ビューから渡されたコンテキストで定義された変数です。(後ほどビューで定義します。)

次にテンプレートを呼び出すようにビューを書き換えます。

from django.http import HttpResponse
from django.template import loader

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = {
        'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context, request))
.
.
.

この時点では、ビュー内のテンプレートの取扱について詳細を追求しなくても良いです。(通常は、後で出てくるショートカットを使って定義するため。)

render に渡すコンテキストで、テンプレートに渡す変数を指定しています。

http://127.0.0.1:8000/polls/ にアクセスして動作を確認します。

質問内容がリストで表示され、リンク表示されています。

ショートカット: render()

ビューでテンプレートを扱う部分を render() ショートカットで書き換えます。

from django.shortcuts import render

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)
.
.
.

HttpResponse を返すためには django.shortcuts.render を利用するだけなので簡単ですね。

render

render(request, template_name, context=None, content_type=None, status=None, using=None)

与えられたコンテキストをテンプレートに結びつけ、描画された HttpResponse オブジェクトを返す。

request
このレスポンスを作成されるために使うリクエスト

template_name
利用するテンプレートのフルネーム

context
テンプレートコンテキストに追加する値のディクショナリ

次回は 404エラーの送出、テンプレートについてのより詳細な検証について記述して行きます。

参考

低価格なのに高速・多機能・高セキュリティ 月額400円(税別)から最大容量100GB WordPress専用高速サーバー Z.com WP
おすすめの記事