request.POST
をいじりたい
動機
以下のようなフィールドを持つフォームを作った。
fields = ('title', 'category_id', 'contents', 'tag', 'valid', 'author')
これはブログの記事を作るためのフォームで、author
(記事の投稿者)は自動でログインしているユーザのオブジェクトを代入したい。テンプレート内にこれを表示してしまうと、自由に投稿者を操作できてしまう。それだとアカウント制の意味がない。なので、テンプレートにauthor
のフォームは表示しない。
しかし、POSTされた情報をviewsで処理するときform.save()
をすると「author
がないよ」とエラーが返ってくるので(当たり前)views内で別途author
をrequest.POST
に追加する必要があった。
追加してみる
ここで安直にrequest.POST['author'] = 'ジャスティン・ビーバー'
と代入しようとするとエラーが返ってくる。request.POST
はイミュータブルだから代入できないよ。というエラーが。どうしたものかと調べてみると2つの解決策を見つけた。
解決策その1 copy()
ひとつはcopy()
でごっそりコピーする方法。
req = request.POST.copy()
これでコピーしてreq['author'] = 'ビル・ゲイツ'
とすればちゃんと追加される。めでたしめでたし。
解決策その2 ミュータブルにする
もうひとつは、イミュータブルならミュータブルにすればいいじゃない。というやり方。
request.POST._mutable = True
これでrequest.POST
がミュータブルになって追加することができる。処理が終わったら再びイミュータブルにするのも忘れない。
request.POST._mutable = False
変数を追加しなくていいからこっちを採用した。が……
が……Django軽犯罪法違反な気がする
そもそもイミュータブルなのにはきっと何かしらの理由がある。それをいじって無理やりデータを追加するのはかなり行儀が悪い気がする。あんまり良い気分はしなかった。だから他の方法でなんとか解決しようとしたが、苦肉の策でこうなってしまった。何か別のやり方を調べねば。それかこういう状況に陥らない設計を考えるか。
反省室
というわけでrequst.POST
に修正を加えることについて少しディグってみた。
やっぱりrequest.POST._mutable = True
を推奨している人なんていませんね。禁断の果実に手を伸ばしたようです。反省。無理やりどうこうするようなやり方はよくない。うまいことやれる大人にならないと。明日リファクタリングだ!
P.S そしてこれを書いている真っ最中にレビューで「request.POST
はいじらないよ!」というコメントをいただく。肝に銘じます。