しゃちの備忘録

プログラミングを中心とした技術関連の備忘録です(今のところ)

Djangoに触る(その4)

4日目です.

チュートリアルの続きに挑みます

前回まで

teru0rc4.hatenablog.com

テーブルの作成についての整理と, チュートリアルを進めadminのセッティングを行いました..

今日やったところ

はじめての Django アプリ作成、その 3 | Django documentation | Django

ビューに関して,polls/view.pyなどを修正しました.

ビューの追記

前々回pollsにアクセスした時のビューを結構あっさり作ったのですが, 今回はそこの部分をもう少し掘り下げ,かっこいい見た目にしていこうと思います

polls/view.pyを次の内容を追記します.

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)

また,polls/url.pyの内容は以下のように書き換えます. url()を追記して,更新した`polls/view.pyに対応する形にしました.

from django.conf.urls import url

from . import views

urlpatterns = [
    # ex: /polls/
    url(r'^$', views.index, name='index'),
    # ex: /polls/5/
    url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
    # ex: /polls/5/results/
    url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
    # ex: /polls/5/vote/
    url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]

この状態でpython3 manage.py runserverをし, http://127.0.0.1:8000/polls/29/にアクセスをするとこのような画面になります.

f:id:teru0rc4:20170903004104p:plain

http://127.0.0.1:8000/polls/以下に数字を入れてアクセスすると,URLで指定した数字が出力されます.

何が起きているのかというと, たとえば,今回のようにhttp://127.0.0.1:8000/polls/29/に対してアクセスし,リクエストを送ると, Djangomystic/setting.pyの中のROOT_URLCONF = 'mysite.urls'という部分を参照し, mystie/url.pyをロードをします.

mystie/url.pyに従い与えられたURLを検査しpolls/に該当する処理を見つけたあと, /pollsを取り除いた残り/29polls/url.pyに引き渡し, この表現がr'^(?P<question_id>[0-9]+)/$'に合致するのでdetailを呼び出してその結果として, URLにIDを打ち込むだけで,対応した画面を出力してくれるというわけです.

これの強みとしては,URLのマッチングには正規表現を使っているため,基本的に制限はなく, 同時に.htmlなどの追加もいらない点が挙げられます.

ちゃんと動作を持つビューを作る

ここまでではあくまで表示しているだけで,ビューにとって大事な要素を満たしているとは言えません.

それはリクエストに対して季節なHttpResponseを返すことと,例外をしっかり返すことです. 以降ではそれらをindex()を変更しながら実装したいと思います.

まずはpolls/views.pyを次のように追記いたします. やっていることは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)

しかしこのコード,記法状は問題はないのですが,システムとして問題を抱えています. それはビューの内容を直接書き込んでしまっていることです. このままでは,ページの見栄えを変更するたびにこのPythonコードを編集せねばなりません.

そこで,このビューの部分をPythonから切り離したいと思います. そのためにDjangoのテンプレート機能とhtmlファイルを利用します.

まずはpollsディレクトリの中にtemplatesというディレクトリを作成します. そしてその中にpolls(誤字ではないです)を作成します. そしてその中にindex.htmlを作成します. つまりpolls/templates/polls/index.htmlになるわけです.

何故こんなことをしているのかというと,Djangoのテンプレートのロードと, 同名のテンプレートを作った際の区別を簡単に明確化する目的があります. 詳しくは公式ドキュメントに書いてあるので是非ご参照ください(はじめての Django アプリ作成、その 3 | Django documentation | Django)

肝心のindex.htmlですが次のように記入します.

{% 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 %}

また,テンプレート適用のためにpolls/view.pyindex()も次のように変更します.

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))

この状態でサーバーを立てpolls/にアクセスすると,questionの質問リストを表示します. 何もなければNo polls are availableと言われます 質問を追加する場合は

はじめての Django アプリ作成、その2 | Django documentation | Django

を見ながら追加してみましょう.

おわりに

ビューのリクエストまで作成しました.

明日はもうちょっと進めるといいですね….

というか,機能はなんとなくぽよっとわかったので, 1回思ったものがどこまでできるかーをやってもいいのかなーと思ってたりします.

うーん.