django.views.generic.base.TemplateViewなどのクラスベースビューの実装を見てみると、head()メソッドが書かれていないように見える。しかしHEADリクエストには対応してる、という話。
「TemplateViewはHEAD対応していない」的なお話を聞くことがあるから書いておく。
環境
Django 1.4
head()はたしかに実装されていない
class TemplateView(TemplateResponseMixin, View): """ A view that renders a template. """ def get_context_data(self, **kwargs): return { 'params': kwargs } def get(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) return self.render_to_response(context)
https://github.com/django/django/blob/1.4/django/views/generic/base.py#L113
( ´゚д゚`)ナイワー
でもHEADリクエストには対応している
試しにお話してみる
% telnet hirokiky.vir 8000
Trying 192.168.56.101...
Connected to hirokiky.vir.
Escape character is '^]'.
HEAD / HTTP/1.0
Host: hirokiky.virHTTP/1.0 200 OK
Date: Tue, 25 Sep 2012 12:11:32 GMT
Server: WSGIServer/0.1 Python/2.7.1+
Content-Type: text/html; charset=utf-8
対応してますやん。
こんなかんじのを動かしてる。
url(r'^$', TemplateView.as_view(template_name='myapp/index.html')),
ちなみにGETで
% telnet hirokiky.vir 8000
Trying 192.168.56.101...
Connected to hirokiky.vir.
Escape character is '^]'.
GET / HTTP/1.0
Host: hirokiky.virHTTP/1.0 200 OK
Date: Tue, 25 Sep 2012 12:50:01 GMT
Server: WSGIServer/0.1 Python/2.7.1+
Content-Type: text/html; charset=utf-8
test
aaa
Connection closed by foreign host.
なんでheadが無いのに返ってくるのか
django.views.generic.base.Viewのas_viewを見れば分かる
as_viewは内部で定義しているviewという関数を返すんだけど、それは
def view(request, *args, **kwargs): self = cls(**initkwargs) if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get return self.dispatch(request, *args, **kwargs)
https://github.com/django/django/blob/1.4/django/views/generic/base.py#L44
こうなってる。
getがあって、headがないクラスの場合にはheadにgetを設定してる
これでheadが無いときでもレスポンスを返してくれる。
そんで多分どっかのレイヤで
「HEADの場合はレスポンスのヘッダだけ返す」
ってなってくれてるんだと思う。
だから self.head = self.get しても問題ない。
じゃぁその「どっかのレイヤ」ってどこ?
というのはまだ分かってないから読んでいく。
ちなみに1.3では無い
def view(request, *args, **kwargs): self = cls(**initkwargs) return self.dispatch(request, *args, **kwargs) # take name and docstring from class update_wrapper(view, cls, updated=())
https://github.com/django/django/blob/1.3/django/views/generic/base.py#L45
上記のように。
1.3 の場合はうまいこと実装してやるっぽい。
- http://d.hatena.ne.jp/aitahoge/20111017/1318839374
- Django1.3のClass-based generic viewsを使う - 偏った言語信者の垂れ流し
1.3については上記の記事とソースコード見ただけで、検証はしてない。
他のメソッドのときも対応できんじゃね
じゃぁheadだけじゃなくてpostとかでもいける気がしてしまう。
実際TemplateViewはPOSTメソッドでアクセスすると403が返ってくる。
同じ要領で実装できんじゃね
と思ったら
@hirokiky それ自体は簡単だと思うけど、リクエストパラメーターが渡ってくる方法が違うから、それを抽象化する手段が必要だね。 #Django はあまり知らないんだけど、 Flask だと request.values で get/post 両対応できる。
2012-09-25 21:30:19 via web to @hirokiky
とのこと。
上記参考にして遊んでみます。