Sitemap

Django チュートリアルを進めていく3 (docker-composeを使って)

11 min readMay 24, 2017

--

どうもこんにちは、ごっちです。

前回の続きです。

今回も公式のチュートリアルに則って進めます。

このアプリケーションで作りたいビュー

  • Question の一覧ページ — index
  • Question の詳細ページ — detail
  • Question の結果ページ — result
  • 投票ページ

ビューをごりごり作っていく

polls]views.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/urls.pypolls.urls と結びつけます。

from django.conf.urls import url
from . import views

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

ここで実際に http://localhost:8000/polls/1/ にアクセスしてみると、しっかりと You're looking at question 1. とか表示されます。

URLの設定はここで好きなようにできるけど、スマートにいきたいよね。。っと公式には書いてあります。

今のままの def index: では何も index として機能していないので、書き直します。

polls/views.py を編集します。

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)

そろそろ HTML を触っていきたいですね。HTMLのテンプレートを用意します。

pollsディレクトリ配下に templates ディレクトリを作成します。Djangoは templates からテンプレートを探すようです。

そしてその templates ディレクトリ配下に polls ディレクトリを作ります。これで名前空間を与えます。

っで、今は index のビューを作るので、いま作った polls ディレクトリの配下に 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/views.py を編集します。

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

あと、いちいち HttpResponse() を書くのは非常にめんどくさいので、ショートカットを読み込んで書き直します。

from django.shortcuts import get_object_or_404, 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() を書く必要もなくなりましたし、 import する必要もなくなりました。

ここで、 http://localhost:8000/polls/ にアクセスすると、きちんとリストになっています!

こうなっているはずです。

404

/detail にアクセスしたときに存在しないれこーとの数字を入力したときに 404 エラーを表示させないといけません。

polls/views.py を編集します。

from django.http import Http404
from django.template import loader
from .models import Question

# ...

def detail(request, question_id):
try:
question = get_object_or_404(Question, pk=question_id)
except Question.DoesNotExist:
raise Http404("Question dose not exist.")
return render(request, 'polls/detail.html', {'question': question})

これで、リクエストしたIDが存在しない場合は404として処理されます。

render するので、 polls/templates/polls/detail.html を作ります

ショートカット

ここもいちいち、try して、存在しない場合は except をするのはめんどくさいので、そのへんのものもインポートして polls/views.py を編集します。

from django.shortcuts import get_object_or_404, render
from .models import Question

# ...

def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})

なんで、 ObjectDoesNotExist 例外をキャッチしないで、ヘルパー関数の get_object_or_404() を使うんでしょうね?

チュートリアルのドキュメントによると

答えは、モデルレイヤとビューレイヤをカップリングしてしまうからです。 Django の最も大きな目標の一つは、ルーズカップリングの維持にあります。いくつかの制御カップリングは、 django.shortcuts モジュールの中にあります

とのことです。

detail のテンプレート

もう少し polls/templates/polls/detail.html を編集します。

<h1>{{ question }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

選択肢のテキストも表示させます。

index のハードコード部分の削除

polls/templates/polls/index.html のリンクの部分がハードコーディングされているので修正します。

<li><a href="{% url 'detail' question.id %}">{{question.question_text}}</a></li>

これで、 polls/urls.py の設定が変更されても対応ができます。

URL の名前空間

同一プロジェクトのほかのアプリとURLが衝突しないように、 polls/urls.py を編集します。アプリケーションの名前空間を設定するのには、 app_name を追加します。

from django.conf.urls import url

from . import views

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

名前空間を追加したので、さっきの polls/templates/polls/index.html のaタグのリンクを修正します。

<li><a href="{% url 'polls:detail' question.id %}">{{question.question_text}}</a></li>

いい感じにできあがってきているはずです。

今日はここまで。。

所感

今回はコマンドでごにょごにょすることはなかったですね。まぁ、サーバーを立ち上げるのにコマンドを入力しますけどね!!

References

Originally published at gist.github.com.

--

--

No responses yet