Archive@2007/11
DjangoでPUTやDELETEやってみたメモ
Django でリクエストをPUTとかDELETEで投げる時に、 ちょろっとハマったのでメモ。
jQuery や Flash からPUTやDELETEでリクエストすると、 メソッド自体はちゃんと解釈されるものの、 なぜか渡したデータが取れなかった。 Pylons ではハマらなかったのになぁ。
で、そもそもデータが渡されてるのかを確かめるために、 Requestのraw_post_dataをプリントしてみると、 そこにはちゃんと入ってた。 データの受け渡し自体はちゃんと出来てるらしい。
じゃあ、次はどこでパースしてるか?って事で、 django.core.handlers.wsgi.py を追いかけてみる。
どうやら111行目あたり、 WSGIRequest のメソッドの _load_post_and_files がパースしてるみたいなのですが、 ここで原因を発見。
def _load_post_and_files(self):
# Populates self._post and self._files
if self.method == 'POST': #<-- ココ
if self.environ.get('CONTENT_TYPE', '').startswith('multipart'):
header_dict = dict([(k, v) for k, v in self.environ.items() if k.startswith('HTTP_')])
header_dict['Content-Type'] = self.environ.get('CONTENT_TYPE', '')
self._post, self._files = http.parse_file_upload(header_dict, self.raw_post_data)
else:
self._post, self._files = http.QueryDict(self.raw_post_data, encoding=self._encoding), datastructures.MultiValueDict()
else:
self._post, self._files = http.QueryDict('', encoding=self._encoding), datastructures.MultiValueDict()
どうやらPOSTじゃないとリクエストされたデータをパースしないらしいよ。困った。
django.core.handlers.modpython.py も見てみると、 こちらはContent-Typeのみを見て判別してるみたい。
とりあえず、POSTしか受け付けないのはツライので、 PUTとDELETEも追加して対処する事に。
Index: django/core/handlers/wsgi.py
===================================================================
--- django/core/handlers/wsgi.py (revision 6708)
+++ django/core/handlers/wsgi.py (working copy)
@@ -110,7 +110,7 @@
def _load_post_and_files(self):
# Populates self._post and self._files
- if self.method == 'POST':
+ if self.method in ('POST', 'PUT', 'DELETE'):
if self.environ.get('CONTENT_TYPE', '').startswith('multipart'):
header_dict = dict([(k, v) for k, v in self.environ.items() if k.startswith('HTTP_')])
header_dict['Content-Type'] = self.environ.get('CONTENT_TYPE', '')
とりあえず、コレでPUTやDELETEのデータもちゃんと受け取れるようになったよ。 果たして良いのかどうかは分からんですけども。
これでしばらく様子を見てみよう。
- Posted at:
- 2007/11/26 23:17:49
- 2 Comments
- 1 TrackBack
- Trackback:
- http://humming.via-kitchen.com/2007/11/26/tried-put-and-delete-on-django/trackback/
Vimpi launched!!
yoshuki さんが作ったサービスの Vimpi がスタートしたよ!
自分が使ってる vim のプラグインとか登録しておけば、 Feedで更新が分かるっす。 他の人が使ってる .vimrc とかプラグインも見れたりするので、 参考にするってのも出来ちゃうよ。
vimmer な人は是非ともお試しあれ ![]()
- Posted at:
- 2007/11/21 02:32:44
- 2 Comments
- 0 TrackBacks
- Tags:
- vim
- Trackback:
- http://humming.via-kitchen.com/2007/11/21/vimpi-launched/trackback/
焼き肉食べてきたよ。
本日は久しぶりに焼き肉を啄んで参りました。
perezvon さん、 Voluntas さん、 グニャラ さん、 itsukoさん、そして僕というメンツ。
MiCHiLU さんは用事が重なってしまい今回は不参加。むー、残念 ![]()
普段聞く事が出来ない話とかも、色々聞けてめちゃめちゃ面白かったよ! やっぱり良いっすね。こういうの。 つながりは大切って、改めて思ったっす。
以下ネタ的に。
- perezvon さん、 グニャラ さんはものっ凄いデキる方向。(ガロン単位)
- itsukoさんはHHKの影を感じさせない、とても感じの良い方でした。
- Voluntas さんは寝袋必須。(じゃんけん大会)
- デフォルト・バッファ・キュー・スタックは日本語にはなれない。
次回の予定もあるみたいなので、また是非是非参加したいと思っております ![]()
- Posted at:
- 2007/11/21 00:48:01
- 0 Comments
- 0 TrackBacks
- Tags:
- memo
- Trackback:
- http://humming.via-kitchen.com/2007/11/21/ate-broiled-meat/trackback/
JavaScript-XPathを触ってみたよ。
個人的に XPath がトレンドってのもあって、 JavaScript-XPath を使ってみたよ。
amachang さんの こちらのエントリー で jQuery のバインディングが公開された事を知って、 XPath for jQuery も使ってちょくちょく触ってみたけど、 全く意識する事無く使えて物凄くいい感じ。
ダウンロードはココからしてきたっす。
- JavaScript-XPath
- JavaScript-XPath - CodeRepos::Share - Trac
- XPath for jQuery
- JavaScript-XPath/bindings/jQuery - CodeRepos::Share - Trac
まだまだ大した XPath を書けないので、 キョーレツなテストとかは出来ないけど、 個人的には end() が併用出来るのがめちゃくちゃ嬉しい。 end() って jQuery の重要な機能の1つなので、 これが併用出来るかどうか?でかなり印象が変わってくる(と思う)。
これから常用プラグインとして使っていきそうな勢いなので、 気付いた事とかフィードバックしていけたら良いなぁ。 まずは lxml と JavaScript-XPath で XPath と仲良くならなくちゃね。
- Posted at:
- 2007/11/20 01:53:56
- 0 Comments
- 0 TrackBacks
- Tags:
- JavaScript
- jQuery
- XPath
- Trackback:
- http://humming.via-kitchen.com/2007/11/20/tried-using-javascript-xpath/trackback/
詳解 MySQLが出てたよ。
今日は本屋に行こうと渋谷まで。 目的の本は ActionScript 3.0 アニメーション 。 まぁ、案の定売り切れらしく置いてなかったよ。 前に立ち読みした感じだと、かなり良さそうだったし、 予想してたから凹みはしなかったけど残念。
やる事も尽きたし、帰ろうかと思った矢先に 詳解 MySQL を発見。もう発売されてたんだ。 ちょっとチラ見してみたら、難しそうだけど面白そう。 Understanding MySQL Internals の和訳らしく、 mir the archive と合わせて読むと良いかも知れない。 給料入ったら購入衝動との戦いになりそう。
Cocoa とか Objective-C の本も良いのがあれば欲しいと思ったけども、 渋谷のBook 1stが移転してて、目当ての本がどこにあるのか検討がつかず撃沈。 オススメがあれば教えてくださいまし。
- Posted at:
- 2007/11/18 23:14:07
- 3 Comments
- 0 TrackBacks
- Trackback:
- http://humming.via-kitchen.com/2007/11/18/mysql-internals-released/trackback/
lxmlを試してみたよ。(その2)
前回 に続いて lxml を使って色々やってみたよ。
テスト用のファイルを書くのもメンドクサイので、 このサイトのカテゴリーリストで遊んでみる事にした。
>>> from httplib import HTTPConnection
>>> from lxml import etree
>>> # とりあえずHTMLを取ってくる。
>>> conn = HTTPConnection('humming.via-kitchen.com')
>>> conn.request('GET', '/')
>>> # レスポンスをパース。
>>> html = etree.parse(conn.getresponse(), parser=etree.HTMLParser()).getroot()
ここから lxml でサクサク遊んでみる。
>>> # カテゴリーリストを取ってくる。
>>> html.xpath('//div[@id="subContent"]/ul[@class="cloudList"]')
[<Element ul at 2489f90>]
>>> ul = html.xpath('//div[@id="subContent"]/ul[@class="cloudList"]')[0]
>>> # リストのリンクを取ってくる。
>>> ul.xpath('./li/a')
[<Element a at 2489fc0>, <Element a at 248f720>, ..., <Element a at 248fe70>]
>>> # リンクのテキストを取ってくる。
>>> ul.xpath('./li/a/text()')
['ActionScript', 'AIR', ..., 'vim']
テキストを取りたい場合は text() 、 ならアトリビュートはどうやって取るんだろう?と疑問が。
で、色々調べたり試したりした結果、 @ATTRIBUTE で取れるらしいっす。
>>> # hrefを取ってくる。
>>> ul.xpath('./li/a/@href')
['/weblog/tag/actionscript/', '/weblog/tag/air/', ..., '/weblog/tag/vim/']
>>> # classを取ってくる。
>>> ul.xpath('./li/a/@class')
['rank9', 'rank2', ..., 'rank2', 'rank8']
これが分かると一気に使い勝手が良くなってきた! もうね、 lxml 素敵。ってか XPath 素敵。
- Posted at:
- 2007/11/14 03:00:24
- 0 Comments
- 0 TrackBacks
- Trackback:
- http://humming.via-kitchen.com/2007/11/14/tried-using-lxml-part2/trackback/
lxmlを試してみたよ。
遅ればせながら lxml を試してみたよ。コレ、かなり便利っすなぁ。
インストールは easy_install でするのが簡単で良いと思う。 yolk で検索してみると、2.0alphaとかも出てきたので、 今回はバージョンを指定してインストールしてみた。
$ sudo easy_install lxml==1.3.6
テスト用にこんな感じのXMLを用意して、 test.xml とかで保存。
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<id>1</id>
<name>hoge</name>
<type>word</type>
</item>
<item>
<id>2</id>
<name>hige</name>
<type>word</type>
</item>
<item>
<id>3</id>
<name>hage</name>
<type>image</type>
</item>
</items>
lxml を使って遊んでみる。
>>> from lxml import etree
>>> xml = etree.parse(open('test.xml', 'r'), parser=etree.XMLParser())
>>> xml
<etree._ElementTree object at 0x7406c0>
>>> # ルートノード(items)を取ってくる。
>>> items = xml.getroot()
>>> items
<Element items at 7417b0>
>>> # 子要素(item)を取ってくる。
>>> items.getchildren()
[<Element item at 7417e0>, <Element item at 7418a0>, <Element item at 741840>]
>>> # XPathで子要素(item)を取ってくる。
>>> items.xpath('./item')
[<Element item at 7417e0>, <Element item at 7418a0>, <Element item at 741840>]
>>> # XPathで孫要素(name)のテキストを取ってくる。
>>> items.xpath('./item/name/text()')
['hoge', 'hige', 'hage']
文字列から直接パースする場合は、 etree.fromstring なメソッドを使うと良いらしい。
>>> text = open('test.xml', 'r').read()
>>> items = etree.fromstring(text, parser=etree.XMLParser())
>>> items
<Element items at 7418a0>
文字列からのパースだと、 getroot しなくても直接ルートノードが返ってくる。
逆に、ノードを文字列にしたい場合だと、 etree.tostring なメソッドを使うと良いみたい。
>>> # itemノードの1個目を文字列に。
>>> etree.tostring(items.xpath('./item')[0])
<item>
<id>1</id>
<name>hoge</name>
<type>word</type>
</item>
>>> # 最後のitemノードに含まれるnameノードを文字列に。
>>> etree.tostring(items.xpath('./item[position()=last()]/name')[0])
<name>hage</name>
色々簡単に使えていい感じ。 XPath もちゃんと覚えないとなぁ。 HTMLを扱うときは、 parser を etree.HTMLParser にしてあげれば良いよ。
- Posted at:
- 2007/11/11 19:48:07
- 2 Comments
- 1 TrackBack
- Trackback:
- http://humming.via-kitchen.com/2007/11/11/tried-using-lxml/trackback/
DjangoとMySQLでForeignKeyのつく条件(の続き)
結構前に、 ここらへん で Django を MySQL で動かす場合の、 ForeignKey のつく条件についてやきもきしてた訳ですが、 チケット #5729 で上がってたみたいで、 r6650 で進展があったっぽいよ。
試しに r6649 と r6650 を比べてみる。 models.py は前回と同じようにしてテストする。
from django.db import models
class Oya(models.Model):
body = models.TextField()
class Kodomo(models.Model):
parent = models.ForeignKey(Oya)
body = models.TextField()
これで、 r6649 で sql を叩くとこんな感じ。
BEGIN;
CREATE TABLE `hige_oya` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`body` longtext NOT NULL
)
;
CREATE TABLE `hige_kodomo` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`parent_id` integer NOT NULL REFERENCES `hige_oya` (`id`),
`body` longtext NOT NULL
)
;
これが r6650 だとこう変わる。
BEGIN;
CREATE TABLE `hige_oya` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`body` longtext NOT NULL
)
;
CREATE TABLE `hige_kodomo` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`parent_id` integer NOT NULL,
`body` longtext NOT NULL
)
;
-- The following references should be added but depend on non-existent tables:
-- ALTER TABLE `hige_kodomo` ADD CONSTRAINT parent_id_refs_id_66492efa FOREIGN KEY (`parent_id`) REFERENCES `hige_oya` (`id`);
COMMIT;
変わった事は変わったんだけど、なぜコメントアウト? 「存在しないテーブルへの参照だから。」って言われても、ちゃんとあるんだけどなぁ。
実際作られるテーブルを見てみると、両方とも前回同様こうなった。
mysql> SHOW CREATE TABLE `hige_kodomo`\G
*************************** 1. row ***************************
Table: hige_kodomo
Create Table: CREATE TABLE `hige_kodomo` (
`id` int(11) NOT NULL auto_increment,
`parent_id` int(11) NOT NULL,
`body` longtext NOT NULL,
PRIMARY KEY (`id`),
KEY `hige_kodomo_parent_id` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
#5729 は既にクローズされてるし、実に悩ましい。 って言うより、こういう時にリオープン出来るだけの英語力がない(実力もない)のが何よりも悩ましい。
- Posted at:
- 2007/11/05 22:41:49
- 0 Comments
- 1 TrackBack
- Trackback:
- http://humming.via-kitchen.com/2007/11/05/mysql-foreignkey-on-django/trackback/
Safariで検索フォームをちょっと素敵に。
Safari でちょっとした小ネタを発見。
HTMLのinputで、typeを search にすると、 角丸のいい感じのテキストエリアに変身してくれるっす。
さらに results と autosave を追加すると、 履歴をちゃんと保持してくれるようになる。 results で履歴を保持する数を指定し、 autosave で保存するユニークなID?を指定するみたい。 実際にドコに保存されるかまでは未調査っす。
こんな感じに書くと、
<input type="search"
results="10"
autosave="example.com">
こんな感じになるよ。

Safari (ってか Webkit ?)でしか意味ないけど、 こういうのちょっと素敵。 Firebugで見てもエラー吐かなかったので、 とりあえず良し。
- Posted at:
- 2007/11/04 23:55:38
- 0 Comments
- 0 TrackBacks
- Trackback:
- http://humming.via-kitchen.com/2007/11/04/tips-for-search-form-on-safari/trackback/
Djangoのエラーメッセージがugettext_lazyに。
ちょっと前から Django のtrunkを使うようになっているのですが、 r6520 から r6635 にアップデートしたらログイン部分がエラー吐いて動かなくなった。
ちょっと調べてみると、 r6625 で newforms のエラーメッセージが ugettext から ugettext_lazy に変更されてる。 これが simplejson がシリアライズ出来なくてエラーになっているみたい。
今まであんまり意識した事がなかったので、ちょっとだけ実験してみた。
>>> from django.utils.translation import ugettext, ugettext_lazy
>>> s = u'This field is required.'
>>> # ugettextだとこうなる。
>>> ugettext(s)
u'This field is required.'
>>> print ugettext(s)
This field is required.
>>> # ugettext_lazyだとこうなる。
>>> ugettext_lazy(s)
<django.utils.functional.__proxy__ object at 0x24a0270>
>>> print ugettext_lazy(s)
<django.utils.functional.__proxy__ object at 0x24a2330>
どうやら ugettext_lazy を使うと、 __proxy__ ってオブジェクトが返ってくるらしい。 こいつを simplejson がシリアライズ出来なくてエラーになってた。
ココでもうちょっと実験してみる。
>>> lazy = ugettext_lazy(s)
>>> # unicodeしてみる。
>>> unicode(lazy)
u'This field is required.'
>>> print unicode(lazy)
This field is required.
>>> # encodeメソッドを呼んでみる。
>>> lazy.encode('utf-8')
>>> 'This field is required.'
>>> print lazy.encode('utf-8')
This field is required.
>>> # force_unicodeしてみる。
>>> from django.utils.encoding import force_unicode
>>> force_unicode(lazy)
u'This field is required.'
>>> print force_unicode(lazy)
This field is required.
どうやら明示的に変換してやる必要があるみたい。 遅延評価の流れってのを少し理解出来たような気がする。
どうやるのが正しいのか?ってのをまだちゃんと理解出来てないので、 とりあえず force_unicode を使ってエラーを回避。
そのうちソースも追いかけてみよう。
- Posted at:
- 2007/11/02 01:43:11
- 0 Comments
- 0 TrackBacks
- Trackback:
- http://humming.via-kitchen.com/2007/11/02/change-errormessage-to-ugettextlazy-on-django/trackback/