前回の続きです。前回までで画面を表示するところまでできたので、
・画面から値を受け取る
・受け取った値をDBに格納する
・DBの値を画面に出力する
と、アプリとしての基本動作ができるようにします。
<前々回>
<前回>
やっぱりタイトルって重要ですな・・・
画面からの値を受け取る
前回は素のHTMLを書いただけだったので、値をサーバーに飛ばせる様にします。formのプロパティとしてPOSTを指定してあげます。
<参考:GETとPOST>
画面からサーバーに値を渡す方法として、主に2通りあります。それがgetとpostです。
getは、URLに値を含めてしまう方法。http://hoge.com/?foo=varといったようなURLを見たことがあるかと思います。foo=varの部分が値ですね。foo項目の値はvarだよ、みたいな。
メリットとしては、値をURLとして指定できるのでリンク張る時に値を指定できる。例えばxxページ目を表示するとか、xxx番目のブログ記事を表示するといった場合は、URLdえ指定できる方が便利ですよね。
デメリットとしては、長さに制限があること。あとは、外から丸見えであること。ユーザー名とパスワードをURLに含めちゃいけないのは、想像つくかと思います。
postは、語弊を恐れず言えばHTTP通信の中に値を含めてしまう方法。メリットは、URLがすっきりするのと、値の長さに制限がないこと。デメリットはリンクとして値を渡すことができない。getの逆ですね。
動かしてみよう
さて、この状態で動かすと・・・
しょんぼりですね。で、なぜかというと、理由があります。
Djangoでは、postで値を受け取る際に、CSRF対策というのが自動で入ります。CSRFってなんぞ?と思われるかもしれませんが、攻撃手法の一種です。
mixiが流行ってた時代に、「ぼくはまちちゃん」なんてのが流行ったのがあったんですが忘れられてるよね・・・
えっと、簡単にいうと、自サイトの別ページや他サイトにスクリプトを仕込んで、開いた人にターゲットに対するpostをさせる攻撃手法の一種です。
知らないところから飛んできたリクエストを受け取りたくないわけですが、その判別が難しい。
そこで、Djangoではトークンというランダムな文字列を画面表示時に作成しておき、画面から値が戻ってきた時にそのランダム文字列が含まれていなかったらよそからの攻撃と判断する といった手法を取っています。
今回のエラーは、そのランダム文字列が入っていなかったからなんですね。
CSRFトークンを入れてみよう
やることは簡単。fomタグの中に
{% csrf_token %}
の一文を入れるだけ。こんな感じ。
すると、、、エラーが出なくなります!
HTMLを開いてみると先ほど入っていたランダム文字列が入っているのがわかります。
今度こそ値を受け取ってみよう
画面から、サーバーに値が渡ってくるようになりました。次は、それをプログラムの中で受け取ってみます。
画面から飛んできた値は、views.pyで受け取ることができ、
request.REQUEST
に配列として格納されています。htmlで入力項目の値をnikuとして定義していたので、こちらを取得してコンソール上に吐き出してみます。コードでいうと以下のような感じ。
if request.method == 'POST':
としているのは、これがないと初回表示もrequest.REQUEST['niku']を探しに行ってしまい、結果、値が飛んできてないのでエラーになっちゃうんですね。なので、この一文を入れることによりpostでリクエストが飛んできたか判断し、postの場合のみ出力をするようにしています。
以下のように入力して送信ボタン(今回だと食べたいボタン)を押すと・・・
押すと・・・
受け取れていることがわかります
DBに値を格納してみよう
値を無事受け取ることができたので、続いてこの値をDBに格納してみましょう。
DBとはなんぞ・・・と言いますと、ざっくりいうと値を保存しておく場所で、postgresやmysqlが有名どころでしょうか。お仕事でシステム作るとなると、OracleやSQL Serverなんていうのが多かったりします。
今回は、最初から組み込まれているSQLiteというものを使います。
テーブルを作ろう
普通、テーブルを作る際は、DBに対してcreate table ・・・なんて命令を実行してあげる必要がありますが、Djangoでは不要です。pythonコードから自動実行してくれちゃいます。
views.py等と同じ場所に、models.pyというファイルを作成します。そこに、以下のようなコードを作成します。
from django.db import models class Oniku(models.Model): comment = models.TextField()
from・・・の部分は、ここで利用する部品の宣言。
class Oniku・・・の部分は、Onikuテーブルを作りますという宣言。
comment・・・の部分は、commentカラムはテキストフィールドだよという宣言。
これで、テーブル定義は完成です。
Djangoに認識させてあげて、テーブルを作らせよう
これだけだと定義ができただけで、実際にテーブルはできていません。なので、コンソールからサーバー起動と同じような感じで
python manage.py syncdb
と実行してあげます。
するとテーブルが作られるんですが、「ついでにDjangoの認証システムあるけどご一緒にいかがですか?」と聞かれます。こちらは、管理画面使ったりするときに必要となってきたりするんですが、今回の講座の範疇を超えるのでひとまずnoでいきます。
これで、テーブルが作成されました。DBの中身を見てみましょう。DBは、プロジェクトフォルダ直下にdb.sqlite3という名前で置いてあります。
<アプリケーション名>_<models.pyで指定したテーブル名>でテーブルができていることが確認できます。
views.pyで値をDBに格納する
準備ができたので、次は値を格納してみます。
まず、views.pyにて、先ほどmodels.pyで指定したテーブルを使うよーと宣言してあげます。そして、そのOnikuに値を渡してあげて、save関数を呼んであげることによってDBに値が保存されます。
これで実際に動かしてみると・・・
値が入っていることを確認できます。
画面に値を表示してみよう
DBに値を格納することができたので、次は値の表示です。まずは、DBからviews.pyの中で値を取り出してみます。
取得は簡単。
<テーブルクラス>.objects.all()
だけです。
画面に値を渡してみよう
画面に値を渡すには、contextに対して辞書として値を渡してあげるだけです。
commentsという名前で画面に返してあげるよーと指定している形になります。
画面に表示する
いよいよ大詰めです。画面への表示です。
作ったhtmlを開きます。views.pyで渡したcommentsは複数項目なので、これを一つづつ取り出してあげる必要があります。
{% for <内部で使う名前> in <views.pyで返した名前> %}
〜それぞれの値に対する処理〜
{% endfor %}
とすることによって、一つづつ値が取り出され、内部で使う名前を用いて、その一つづつの要素にアクセスができます。
Djangoでは{% %}を制御文として、{{ }}を画面に表示するものとして扱います。JSPの<% %>と<%= %>みたいなものと言ってわかる人もいるかもしれません。
ここではこんな感じにしてみます。
views.pyから渡されたcommentsの値を、1つづつsakebiとして取り出す。sakebiの中のcommentを画面に表示する。
これで動かすと・・・
画面に表示されました!
・・・ということで、「必要なのはブラウザだけ。Python使ったWebサービス構築」はここまでになります。
もっと詳しく知りたい方は、以下のページなどを参考に。
Django ドキュメント — Django 1.4 documentation
ただ、日本語のこのドキュメント、ちょっと古くてそのまま書いて動かない場合がたまにあります。
その場合は、英語ですが以下のドキュメントを見てみてください
Django documentation | Django documentation | Django
もしくは、僕に質問くれれば、わかる範囲でお答えしますのでTwitter等でお気軽にご質問ください。
最後に
色々と難しい解析を中で走らせます とかじゃなければ、今回一連で説明したものでものが作れちゃうんですよね。
例えばグーグルマップ作りますとかグノシー作りますみたいなのは無理だとしても、クックパッド的なものを作りますとか、mixi的なものを作りますであれば、貧弱だとしても基本的な動作ができるものは作れちゃうわけですよ。
何が言いたかというと、ものを作るっていうのはそんなにハードル高くないよ と。もちろん細かい作り込みや、大量アクセスあった時のさばき方とか、美しい見た目とか、プロがご飯食べれるプロとして存在するだけあって、ややこしいものは色々ある。だけど、趣味でやる範囲ならこれだけで全然いけちゃうんですよね。
今回の一連の記事で、1人でも「僕/私も何か作ってみようかな。というか作ってみるか」と手を動かし始めてみてくれたらと思ってます。
僕も勢いで作りました。みなさんも、勢いで作ってみませんか?nitrous.ioであれば、ブラウザ一つでできるのでオススメです。
<追記>
Twitterで実際にやってみてくれた人みつけました!嬉しいなぁ
今日の成果物 #nitrousio #sqlite3 #python #django pic.twitter.com/xUxNW9evgD
— __a_b_n (@__a_b_s) 2014, 11月 9