Django – render/redirect/HttpResponseなど

概要

ビュー関数/ビュークラスのメソッドはHttpResponseクラスやその派生クラスのインスタンスを戻り値として、テンプレートをレンダリングしたり指定したURLに遷移する。

この戻り値の与え方としては、HttpResponseやその派生クラスのインスタンスを直接与える方法と、django.shortcutsで定義された関数(render、 redirect)を使う方法がある。

HttpResponseはレスポンスボディ―を指定して表示。ショートカットのrenderは引数にテンプレートファイルを指定し、それを表示する。

URLを指定したリダイレクトには、HttpResponseRedirectやショートカットのrenderを使う。

レンダリング

HttpResponse

HttpResponsedjango.httpパッケージのモジュールで、ヘッダーや内容などを持つHTTPレスポンスのクラス。インスタンス生成時に引数にテキストを指定したテキストがレスポンスボディ―になり、直接表示される。

テキストのほか、イテレーターやファイルも指定できる。

render

renderdjango.shortcutsパッケージのモジュールで、指定したテンプレートファイルの内容をHttpRequestインスタンスとして返す。

テンプレートファイルに加えて、テンプレートに引き渡す変数コンテキストも指定できる。

リダイレクト

HttpResponseRedirect

HttpResponseRedirectdjango.httpパッケージのモジュールで、指定したURLに遷移するためのHTTPレスポンスのインスタンスを生成する。

HttpResponseRedirectHttpResponseRedirectBaseを継承し、HttpResponseRedirectBaseHttpResponseを継承している。

ビュー関数/メソッドの中で、URLを引数に与えてHttpResponseRedirectのインスタンスを生成し、戻り値にそのインスタンスを渡すことで、指定したURLにリダイレクトされる。

引数のURLは以下のように与えることができる。

  • ホスト名を含む絶対URL
  • アプリケーション名から始まるサブディレクトリーによる相対URL
  • urls.pypath関数で設定したルート名をreverse関数の引数に与えた戻り値(ルート名を直接与えることはできない)

redirect

redirectはdjango.shortcutsパッケージのモジュールで、指定したURLにリダイレクトするためのHTTPレスポンのためのスインスタンスを返す。

redirectは関数として定義され、デフォルトではHttpResponseRedirectのインスタンスを返すが、引数にpermanent=Trueを設定すると、HttpResponsePermanentRedirectのインスタンスを返す(このクラスは301ステータスを返す)。

redirectHttpResponseRedirectを返す際、resolve_url関数を介していて、reverse関数を使わず直接ルート名を渡すことができる。

 

Django – HttpResponse

概要

HttpResponsedjango.httpパッケージにあり、HTTPリクエストに対してサーバーからクライアントに返されるHTTPレスポンスを表すクラス。

Django Documentation – Request and response objects

プロパティー

HttpResponseは以下のプロパティーを持つ(一部記載)。

status_code
ステータスコードの値
headers
ヘッダーの各項目の内容
content
レスポンスボディの内容。バイトストリング。
charset
文字コード名
reason_phrase
ステータスコードのフレーズ。RFCに準拠。

インスタンス生成例

まずモジュールをインポートし、文字列を渡してHttpResponseインスタンスを生成。インスタンス表現や型を確認。

ステータスコードとステータスフレーズを確認。

ヘッダーとそのうちの文字コードを確認。

ボディー部の確認。バイトストリングになっている。

 

Django – フォームデータ

概要

テンプレートのフォームで入力・送信されたデータをビューで受け取って処理する方法の基本。

ビュー関数/メソッドの引数(たとえばrequest)のPOST配列でフォームのINPUT要素のname属性値を指定して値を取得する。

request.POST['name属性値']

実装例

2つのページへのルーティング

urls.pyinputページとresultページへのルーティングを設定。inputページにフォームを置き、そこから送信されたデータをresultページで表示することとする。

DTLのurlタグを使うため、各ルートにname引数でルート名を付けている。

inputページのためのビュー

ルート名formtest:inputでルーティングされるview関数。単にinput.htmlテンプレートをレンダリングしている。

input.htmlテンプレート

input.htmlテンプレート。フォームには、textタイプのINPUT要素と、3つの選択肢を持つradioタイプのINPUT要素群が置かれている。

  • textタイプのINPUT要素のname属性はinput_test
  • radioタイプの3つのINPUT要素のname属性はradio_choiceで値はpinebambooplum

送信ボタンが押されると、methodで指定したURLに飛ぶが、ここではurls.pyで定義したformtest:resultに飛ぶようにDTLのurlタグを使っている。

resultビュー

フォームからの送信に対してviews.pyresult関数が呼ばれる。result.htmlテンプレートにcontext辞書を介して2つの変数input_textradio_choiceを渡している。

  • input_text変数には、name='input_text'で指定されたテキストの内容がrequest.POST['input_text']で取得されて代入される
  • radio_choice変数には、name='radio_choice'で指定されたラジオボタンのうち選択されたもののvalue値がrequest.POST[‘radio_choice’]で取得され、これに対応する文字列が代入される

result.htmlテンプレート

resultテンプレートでは、ビューのcontextで設定された変数の内容を表示する。

 

Django – DTL – URL

概要

urls.pyでURLパターンからビューへのルーティングを指定しただけの場合、テンプレートでそのルーティングを使うにはURLを直書きしなければならない。

これに対して、urls.pyのURLパターンを任意に変更しても影響が及ばないようにするには、DTLのurlタグを使う。

URLハードコーティングの場合

たとえばmyappアプリケーションのmainページからsubページへのリンクを貼りたいとする。

アプリケーションのurls.pyは以下のようになっているとする。

ルーティングされたビュー関数が以下のように書かれているとする。

レンダリングされるテンプレートでURLをハードコーティングした場合は以下のようになる。

main.html

sub.html

このときのURL指定と各ページの対応は以下のとおり。

  • [DOMAIN]/myapp/ → views.main → main.html
  • [DOMAIN]/myapp/sub → views.sub → sub.html

URLハードコーティングの問題

urls.py中のpath関数のURLのパターンを任意に変化させると、各テンプレート中のURLを全て見直さなければならない。これの影響を及ぼさせないようにしたい。

urls.pyでのname指定

urls.py中、抽象化したいpath関数にname引数を追加する。この場合はsubページへのpath関数を以下のように変更。

そして、subページへのURLの代わりにDTLのurlタグを使い、その引数にurls.pynameで指定した値を与える。

アプリケーションを指定する場合

異なるアプリケーションでnameに指定したい値が重複する場合、[app_name]:[path_name]で指定できるようにする。

path()関数でnameを指定する際、urls.pyの冒頭でapp_name変数にアプリケーション名の文字列を指定しておく。

そして、DTLのurlタグの引数にapp_nameで指定した値を加える。

まとめ

グローバルなパス名の場合

  1. urls.pypath関数にname引数でパス名を指定
  2. URLの代わりに{% url 'パス名' %}を指定

アプリケーションローカルなパス名の場合

  1. urls.pypath関数にname引数でパス名を指定
  2. urls.pyの冒頭でapp_name='アプリケーション名'を記述
  3. URLの代わりに{% url 'アプリケーション名:パス名' %}を指定

 

Django – クラスベースビューの基本

概要

Djangoのビューを実装するのに、関数で書く方法と、Viewクラスやその派生クラスを継承して必要なメソッドをオーバーライドする方法がある。

Djangoのオーソドックスな書き方ではクラスベースビューのListViewなどを利用し、コード量を減らすことが推奨されている。

ここでは関数による方法とViewクラスの継承クラスによる方法の2つを比較する。

基本形

テンプレートの準備

ビューからパラメーターを受け取り、単にそれを表示するテンプレートを準備する。ここではviewtestというアプリケーションを想定し、準備するテンプレートファイルはindex.htmlとする。

関数によるビューの実装

views.pyの記述

アプリケーションディレクトリー下のviews.pyファイルに、indexビューを関数で定義する。ビューではテンプレートに渡すパラメーターを文字列'Hello!'としている。

urls.pyの記述

アプリケーションのサブディレクトリーfunctionから、同じアプリケーションのindexビューへのルーティングを定義する。この例の場合localhost:8000/viewtest/functionのようにURLを指定し、ブラウザーでアクセスすることになる。

ここでサーバー起動状態でブラウザーに先のURLを指定すると、ブラウザーに以下のように表示される。

関数ビューの場合、GETを含むリクエストに対してurls.pyに従ってビューが呼び出され、その内容が実行される。

クラスベースビューによる実装

関数によるビューと同じ処理をクラスベースのビューで実装してみる。ここでは比較のために、関数ビューのコードを残してクラスベースビューのコードを追加していく。

views.pyの記述

クラスベースのビューは、Viewクラスやその派生クラス(ListViewなど)を継承し、getpostなどのリクエストに対応したメソッドを記述する。ここではGETリクエストにのみ反応させるため、getメソッドを実装している。

Viewクラスではgetメソッドは定義されていないが、Viewの派生クラスでGETメソッドでのリクエストがあるとViewクラスのhandlerが実行され、View.get()が実行される。そして派生クラスでget()を定義しているとこれがオーバーライドされたメソッドとして実行される。

参考:Django ViewではHttpメソッド名の関数を定義することができる

urls.pyの記述

クラスベースビューによるメソッドが呼び出されるようにアプリケーションのurls.pypath関数を追加する。

関数ベースの場合はpath関数の第2引数に関数表現のビューモジュールを指定したが、クラスベースの場合はIndexViewの親クラスViewas_view()メソッドを指定している。as_view()メソッドは内部関数view()を通してdispatchメソッドを返すので、結局パスが解決されるとdispatchメソッドが呼び出されることになる。

ここでサーバー起動状態でlocalhost:8000/viewtest/classなどとURLを指定すると、ブラウザーに以下のように表示される。

URLパラメーターを含む場合

関数によるビューの実装

urls.pyの記述

URLパラメーターを含む場合、URLパターンに型名やパラメーター名を入れる。

views.pyの記述

ルーティングで記述したパラメーター名をビュー関数の引数に指定し、これをテンプレートに渡す。

ここでサーバー起動状態でlocalhost:8000/viewtest/function/1などとURLを指定すると、ブラウザーに以下のように表示される。

クラスベースによる実装

urls.pyの記述

URLパターンにURLパラメーターを記述する方法は関数の場合と同じ。クラスベースビューの場合はas_viewメソッドの実行結果を渡す。

views.pyの記述

クラスベースビューの場合、getなどのメソッドの引数にパラメーターを指定する。引数の指定パターンは関数の場合と同じ。

ここでサーバー起動状態でlocalhost:8000/viewtest/class/2などとURLを指定すると、ブラウザーに以下のように表示される。

GET/POST処理

関数によるビューの実装

テンプレートの準備

GETで表示されるページにフォームを追加し、送信先をfunctionサブディレクトリー、メソッドをPOSTとする。

urls.pyの記述

今回のindexテンプレートはGET、POST両方のリクエストから呼び出されるため、functionサブディレクトリーのルーティング1つ。

views.pyの記述

リクエストメソッドの違いはrequest.methodの文字列で判定して処理を分ける。GETリクエストの場合は1つ目のifブロックが実行され、テンプレートに文字列'GET!'が渡される。またPOSTリクエストの場合は2つ目のifブロックが実行され、テンプレートには文字列'POST!'が渡される。

ここでサーバー起動状態でlocalhost:8000/viewtest/functionなどとURLを指定すると、views.index関数でGETに対応したifブロックが実行され、ブラウザーに以下のようにGET!と表示される。

このページで「送信」ボタンを押すと、今度はviews.index関数でPOSTに対応したifブロックが実行され、ブラウザーにPOST!と表示される。

クラスベースによる実装

テンプレートファイルの準備

POSTに対する処理を関数の場合と分けるため、送信先のURLのサブディレクトリーをclassとする。

urls.pyの記述

GET/POSTに関わらず、classサブディレクトリーでのリクエストを受け取った場合には、IndexViewクラス(のインスタンス)に処理を渡すように定義。

views.pyの記述

ルーティングで

ここでサーバー起動状態でlocalhost:8000/viewtest/classなどとURLを指定すると、views.IndexViewクラスでオーバーライドしたgetメソッドが実行され、ブラウザーに以下のように表示される。

このページで「送信」ボタンを押すと、今度はviews.IndexViewクラスでオーバーライドしたpostメソッドが実行され、ブラウザーに以下のように表示される。

クラスベースビューの基本のまとめ

要点

基本のクラスベースビューの要点は以下のとおり。

  • Viewクラスを継承したクラスを定義
  • GETやPOSTなどに対応したメソッドを定義
  • ルーティングでは、継承先のクラスの.as_view()メソッドを渡す

views.pyの記述

  • django.views.genericパッケージのViewモジュールをインポート
  • Viewクラスを継承したクラスを定義
  • getメソッド、postメソッドなどを定義
    • 第1引数はself
    • 第2引数はrequest
    • パラメーターがあればそれ以降
  • getメソッドの記述内容は、関数ベースの場合の内容と同じ
    • たとえばrender(request, 'target_page')

urls.pyの記述

  • urlpatterns属性のpath関数の第2引数でビュークラスを指定し、このときas_viewメソッドを指定する
    • たとえばpath('sub_dir', views_dir.MyViewClass.as_view())

 

古事記~土地~伊賦夜坂

概要

黄泉の国の伊邪那美神から伊邪那岐神が逃げおおせた場所(黄泉平坂)。黄泉の国と現世との境。

伊賦夜坂

国道9号から脇に入るとこのような案内がある。この案内に沿って車で入っていける。

その先に車を数台停められるくらいの平場がある。

黄泉平坂に関する説明。左には伊邪那岐神・伊邪那美神から神倭伊波礼毘古命(神武天皇)に至る簡単な系図が書かれている。

駐車場所から一段高いところに小径があり、このような石柱の門があった。このあたりで、静かだが軽く張り詰めたような雰囲気が漂う。

その先にある大岩。これが黄泉の国との境のようだ。

大岩の間からそっと先に進むとさらに狭い小径があるが、その先は細くなって林の中へ消えている。先へ歩を進めるのは憚られた。

戻ったところに木があり、立札によるとこれが伊邪那岐神を救った桃ノ木とのこと。伊邪那岐が桃に対して「汝(なれ)、吾(あれ)を助けしが如く、葦原中国に有らゆるうつしき青人草の、苦しき瀬に落ちて、患(うれ)へ惚(なや)むときに助くべし」と告げ、意冨加牟豆美命(おおかむずみのみこと)の名を与えたとある。

宣伝看板。伊邪那美命を祭った揖夜神社や、この場所が映画の題材になった場所であることなどが紹介されていた。

梅雨入り前、晴れて少し蒸し暑い日だったが、たまたま他にこの場所を尋ねる人もなく、独特の雰囲気が漂っていた。古来の土地を訪ねるのに、他の人の有無・多寡はその印象に影響を与えるのかもしれない。

 

 

古事記~土地~天岩戸神社・天安河原

概要

西宮と東宮の2つがあり、西宮で天照大御神が須佐之男命の乱行を恐れて隠れた岩戸を遥拝できる。

西宮の少し先に天安河原宮があり、そこで思兼神を中心に八百萬神が、岩戸から天照大神を連れ戻す策を相談したとされる。

神社

天岩戸神社の鳥居。想像していたよりもシンプル。

神社本殿。この脇に待合休憩所があり、30分ごとに神職の方に天の岩戸の遥拝所まで案内していただける。

天の岩戸の遥拝所。岩戸は撮影禁止。川向うに洞穴があり入口には半分閉じかけた岩壁があった。注連縄(しめなわ)に右から七・五・三の紙垂(しで)が下がっていた。

境内にある招霊木(おがたまのき)。天鈿女命(アメノウズメノミコト)がこの木の枝を持って踊ったと言われる。

神社由来。御祭神は天照大神で、手力男命(タヂカラオノミコト)と天鈿女命が合祀されている。

神社で時折見かける鶏。ここでも幾羽かいた。

天安河原宮

天岩戸神社西宮の上流側、車道から入っていく道がある。

渓谷の脇、細い道を歩いていく。

天安河はもう少し開けたイメージだったが、深山幽谷の雰囲気。

ここが天安河原。洞窟があるのは意外だった。古事記の話はそっちのけでみんな石を積んでいる。県の観光ポスターにそんな写真が載っているので仕方ないが、そんなセンスに興ざめ。ここでも紙垂が右から七・五・三となっている。

八百萬神が集まるにはちょっと狭い。小さく化身したのかも?