読者です 読者をやめる 読者になる 読者になる

We All Get Old - Naskin Diary

Yet Another My Life On The Web

Google App Engine(Python) の Query class の filter() method メモ

F1世界選手権サーキットMAPの勝利者サーキットMAP表示で


http://f1-circuit.appspot.com/winner/Kimi Räikkönen


のようなリスエストを送ってキミ・ライコネンだけが勝利したサーキットだけ表示しているんだけど、「Kimi Räikkönen」という文字列がデータを保存する put() の時は問題なかったけど、クエリーを処理する filter() で使うとエラーが出るので「Kimi Raikkonen」というアスキー文字列にして問題を回避していた。

class example(webapp.RequestHandler):
    def get(self, name):
        name = urllib.unquote(name)
        driver_queue = winner.all().filter('name = ', name)    # ここで例外発生


リクエスト時にスペースが「%20」になるので urllib.unquote() でスペースに戻すのは前からやっていた。


問題はウムラウトが付いた文字でリクエスト時には「Kimi%20R%C3%A4ikk%C3%B6nen」になっている。


このままクエリー(filter())に使うと「UnicodeDecodeError」例外が発生して、「 'ascii' codec can't decode byte 0xc3 in position 6: ordinal not in range(128)」みたいなエラーがでる。


対話型インターフェースでも再現した。

Python 2.5.1 (r251:54863, Feb  6 2009, 19:02:12) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib
>>> urllib.unquote('Kimi%20R%C3%A4ikk%C3%B6nen')
'Kimi R\xc3\xa4ikk\xc3\xb6nen'

>>> unicode('Kimi R\xc3\xa4ikk\xc3\xb6nen').encode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 6: ordinal not in range(128)


>>> unicode(u'Kimi R\xc3\xa4ikk\xc3\xb6nen').encode('utf-8')
'Kimi R\xc3\x83\xc2\xa4ikk\xc3\x83\xc2\xb6nen'


ということで filter() に渡す前に unicode() に変換してから渡せばOK。

class example(webapp.RequestHandler):
    def get(self, name):
        name = urllib.unquote(name)
        driver_queue = winner.all().filter('name = ', unicode(name, 'utf-8'))

ということにこの前やっと気付いた。