目的
これからプログラミングを学ぼうとする初心者が「はじめてのDjangoアプリ作成」を順番通りにやって、そのときそのときに思ったこと感じたことを記録する備忘録。+記事を書くことで最後までやり通すためのモチベーション維持。ただいま「はじめてのDjangoアプリ作成その3」やってます。
環境
ThinkPad T440p
Ubuntu Linux 18.04 日本語 Remix
Python 3.6.7
pip 9.0.1
Django 2.1.3
前回までのあらすじ
find や locate コマンドで探って、Django 本体の居場所や、どこから import してるのかわかった。「 Django とは web フレームワークだ!」と言われて、なんだかすごい謎めいたものだと思っていたけれど、その正体は、結局いろんなモジュール(脳内イメージでは Python プログラムが書かれた紙の束)が整理されていっぱい詰まっているフォルダなんだなと。幽霊の正体見たり枯れ尾花。
少しずつコードが読めてきている実感はあり。読むことはできるが自分で書くことはまだできないなぁと思う。カスタマイズしながらの実験が必要だろう。ここ何日かでわずかばかりの知識を入れてチュートリアルを読み直すと、前とは違った風景が見えてくるので楽しい。
もっとビューを書いてみる
views.pyの一部を自分なりに解釈する。
def results(request, question_id):
response = "You're looking at the results of question %s."
return HttpResponse(response % question_id)
# results関数つくったよ。request と question_id 受け取って
# response っていう変数に "You're ~" 入れてね
# でそのYou're に question_id 入れて返して
で、合ってる??で/pollsapp/urls.py の解釈
from django.urls import path
from . import views
urlpatterns = [
path('<int:question_id>/results/', views.results, name='results'),
# djangoのurlsからpathをインポートせよ
# 今のフォルダからviews.pyをインポートせよ
# このurlパターンを探せ
# 数字がquestion_idで/results/って続いているやつならば
# 名前がresultsを探してviews.pyのresultsを表示せよ
実際に動作するビューを書く
上記と同じ/pollsapp/urls.py をさらに改造する
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)
# index関数をつくって リクエストあるよ
# latest_question_list という変数にQuestionオブジェクトを
# 最新から5個並べて入れてね
# output という変数に次の内容入れて
# latest_question_listからqを繰り返してtext表示して「,」で連結して
# そのoutput を返して
次にtemplatesディレクトリをつくり、そのしたにpollsappディレクトリをつくり、さらにindex.htmlをつくる。これはデザインとテンプレートを分離するため。名前空間(というものの、親ディレクトリが姓で、サブディレクトリが名前になってたら区別つくでしょ、ってことなんだろう)を利用するとDjangoも読む場所を間違えない。
さらに pollsapp/templates/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 %}
# もしlatest_question_listにquestionがあるなら
# リンクを/pollsapp/数字/に張れ
# それ以外は「No polls ~」と表示せよ
で、このテンプレートを利用するために pollsapp/views.py を更新
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))
# index.html を読み込んで、template に入れて
# latest_question_listを読み込んで
# contextとrequestをテンプレートでレンダリングしてそれをHttpResponseで返せ
context って何だ?とググったら、以下のサイトが参考になった。Document1.0活躍中。やっぱり訳の上手い下手ってあるんだなぁ。document1.0のほうがなんかしっくりくる。自分がピンと来たところを適時引用する。
テンプレート (template) とは、 Django テンプレート言語を使ってマークアッ プしたテキストドキュメントや Python 文字列です。テンプレートには ブロックタグ (block tag) や 変数 (variable) を入れられます。
ブロックタグ はテンプレート中で何らかの処理を行う部分を表すシンボルです。
とはいえ、この定義はいささか曖昧ですね。例えば、ブロックタグを使うと、何ら かのコンテンツを出力したり、制御構造 (“if” 文や “for” ループ) を記述したり、 データベースからコンテンツを取り出したり、他のテンプレートタグにアクセスし たりします。
ブロックタグは "{%" と "%}" で囲みます。
変数は "{{" と "}}" で囲みます。
コンテキスト (context) はテンプレートに渡される「変数名」から「変数の値」 へのマッピングです。
テンプレートの レンダリング (rendering) では、コンテキストから値を取り 出して変数という「穴」に埋め、全てのブロックタグを実行します。
ショートカット: render()
render() 関数は、第1引数として request オブジェクトを、第2引数としてテンプレート名を、第3引数(任意)として辞書を受け取ります。この関数はテンプレートを指定のコンテキストでレンダリングし、その HttpResponse オブジェクトを返します。
ということだったが、さっきの return HttpResponse(template.render(context, request))
ここのrenderは第2引数でrequest受け取ってる。なぜ?まあいいや。このまま進もう。
404 エラーの送出
構文エラーと例外処理は違うらしい。try と except は例外処理で使うやつと。
def detail(request, question_id):
try:
question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
raise Http404("Question does not exist")
return render(request, 'polls/detail.html', {'question': question})
# detail関数を作るよ request と question_id で
# question に id 入れるけど
# 例外起きたら
# Http404 を立ち上げてね
# そうじゃなかったらdetail.htmlを返してね
ショートカット: get_object_or_404()
このあたりでだから何という感じ。結局どれを使えばいいのと。いくつもの選択肢があるのはわかるが、まずは太い幹を教えてくれと言いたい。でこのあたりでけっこうハマったのはコードのどの部分を書き換えたり残したりすればいいのかわからなかったから。それにプログラムを実行して出てきた結果が、正しくHttp404を表示しているか、実はプログラムのエラー画面が出ているのか区別がつかなかったからである。
初心者は「修正前」→「修正後」 のようなコードの違いがわかるモノがあると助かる+結果表示がどんなものかわかると、え?これ本当に正しいの?とまごつかなくてすむ
テンプレートシステムを使う
ふーん。
テンプレート内のハードコードされたURLを削除
ハードコードがあまりよろしくないのはURLの変更が難しいからとのこと。まあふんわりとシステムをつくって余裕をもたせてるって感じなのかな。なるべく抽象化しとくと楽だよってことなのか?
URL 名の名前空間
いっぱいアプリあったらどの View を使っていいかわかんなくなるから、名前空間つけようねとのこと。これも url.py で管理するらしい。
初心者は疲れてきたらちょっとどうでもよくなってくるかな
こんな感じでひとまず区切りつけて、チュートリアル(4)に進もう。