2014年04月27日

jinja2でMarkupしたのにescapeされてしまう問題

今回は jinja2 のカスタムフィルターではまった話。

そもそも GAE + jinja2 で autoescape をしたくなければ、main.py などで
application = webapp2.WSGIApplication(
        [
# 省略
        ],
        config = {
                'webapp2_extras.jinja2': {
                        'environment_args': {
                                'autoescape': False,
                                'auto_reload': False,
                                'extensions': ['jinja2.ext.i18n','jinja2.ext.autoescape']
                        },
        }
)
と autoescape を False にしておけば OK ですが、ユーザに投稿させるようなサイトの場合、言うまでもなく autoescape させるべきです。
その場合、autoescape は True にしておいて、escape させたくない jinja2 の変数では、
{{hoge|safe}}
とやればその変数 hoge に関しては escape が行われません。
将来的に問題になる可能性があるので、safe フィルターは使わない方が良いとは思いますが。

カスタムフィルターを作る場合、例えば、入力された文章の改行を <br /> に変更したい場合、
def linebreaksbr(s):
    return Markup('<br />'.join(jinja2.escape(s).splitlines()))
という感じで、戻りを Markup クラスのインスタンスにしてやれば、autoescape が True でもここで追加した<br />はescape されません。
今回、入力された文章の一行一行を <li></li>で囲ったものを出力しようと思い、
def linebreaksli(s):
    result = ""
    logging.error(type(result));
    for line in jinja2.escape(s).splitlines():
        result += u'<li>' + line + u'</li>';
    return result;
というフィルターを作ってみたのですが、肝心の <li> が &lt;li&gt; と escape されるという問題が発生。 若干、ハマってしまいましたが、そもそも jinja2.escape(s) の戻りが Markup クラスのインスタンスになっていて、Markup クラスのインスタンスに + で unicode 文字列を連結しようとすると、unicode 文字列が escape されて連結されてしまうというだけでした。
def linebreaksli(s):
    result = u''
    logging.error(type(result));
    for line in jinja2.escape(s).splitlines():
        result += Markup(u'<li>') + line + Markup(u'</li>');
    return result;
という風にしてしまえば OK でした。
ラベル:GAE jinja2
posted by おちエン at 21:01| Comment(0) | GAE | このブログの読者になる | 更新情報をチェックする

2014年03月16日

ローカル環境に本番データをリストア

Google App Engine の本番のデータをフルダンプして、ローカル環境(テスト環境)で使ってみようとしたところ、かなりはまってしまいました。。。
ローカル環境は、MacOS の Google App Engine です。

フルダンプ(バックアップ)自体は簡単で、
appcfg.py download_data 
 --url=http://xxx.appspot.com/_ah/remote_api 
 --filename=fulldump
とするだけ。※長いので折り返していますが、コマンド行では一行で書く必要があります。
格納されているデータの量に依存しますが、そこそこ時間はかかります。
Datastore Read Operationsがかなり上がるので、数多くのアクセスがあるサイトは要注意です。

はまったのはローカル環境へのアップロード。
正解は、まず
sudo appcfg.py upload_data 
 --url=http://localhost:8080/_ah/remote_api 
 --filename=fulldump  
 --application=dev~xxx
とすること。--application の appid の指定で dev~をつける必要があります。
dev~ なしの appid を指定すると、
google.appengine.api.datastore_errors.BadRequestError: app "dev~xxx" cannot access app "xxx"'s data
というエラーになってしまいます。

さらに重要なのが、Email の入力できちんと @gmail.com まで入れるということです。
そうしないと
[ERROR   ] Exception during authentication
Traceback (most recent call last):
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/bulkloader.py", line 3469, in Run
    self.request_manager.Authenticate()
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/bulkloader.py", line 1332, in Authenticate
    remote_api_stub.MaybeInvokeAuthentication()
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/remote_api/remote_api_stub.py", line 740, in MaybeInvokeAuthentication
    datastore_stub._server.Send(datastore_stub._path, payload=None)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/appengine_rpc.py", line 423, in Send
    self._Authenticate()
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/appengine_rpc.py", line 564, in _Authenticate
    super(HttpRpcServer, self)._Authenticate()
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/appengine_rpc.py", line 360, in _Authenticate
    self._GetAuthCookie(auth_token)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/appengine_rpc.py", line 293, in _GetAuthCookie
    response.headers, response.fp)
HTTPError: HTTP Error 200: OK
[ERROR   ] Authentication Failed: Incorrect credentials or unsupported authentication type (e.g. OpenId).
というエラーが表示されてうまくいきません。

分かってしまえば簡単なことなのですが、かなりはまってしまい、
を参考に、Charles Proxy app などをインストールしたりしてしまいました。。。
言うまでもなく、Charles Proxy app をインストールしてもうまくはいきませんのでご注意を。

ラベル:GAE appcfg.py
posted by おちエン at 05:34| Comment(0) | GAE | このブログの読者になる | 更新情報をチェックする

2013年05月19日

GAEで独自ドメイン

GAEで独自ドメインの設定の仕方をいつも忘れるので、備忘録。

まず、GAE の管理サイト(https://appengine.google.com/)にアクセスします。
独自ドメインを設定したい application を選択します。
メニューの Administration にある Application Settings をクリック。
ページの真ん中辺りに Domain Setup の Add Domain をクリック。

GAE で独自ドメインを使うためには Google Apps に登録する必要があります。
右のボックスの「Sign up for Google Apps Standard」をクリックすると、無料 Google Apps の登録ページに飛べます。
必要事項を入力して登録します。

登録が完了すると、ドメインの所有確認になるので、DNS の設定をして、所有権を確認させます。
; google
    IN  TXT "google-site-verification=xxxxxxxxxxxxxxxxxxxxxxxxxxx"
を入れて、DNS を再起動するだけです。
もちろん、DNS の Serial も変える必要はあります。
登録が完了したら、もう一度、GAE の設定ページに戻って、もう一度、Add Domain を押して、設定するドメインを入力。
残念ながら、ホスト名なしの URL、例えば google.com は GAE で使えません。
www.google.com というような形にする必要があります。
ホスト名を設定したら、再度、DNS を変更します。
www IN  CNAME   ghs.googlehosted.com.
というような項目を追加して、DNS を再起動。
設定した URL にアクセスして、サイトが見れれば完了です。
posted by おちエン at 14:39| Comment(0) | GAE | このブログの読者になる | 更新情報をチェックする

2013年01月08日

fancy_urllib.InvalidCertificateException: Host appengine.google.com returned an invalid certificate の対応

GoogleAppEngineLauncher を update した後に appcfg.py で deploy しようとしたところ、
fancy_urllib.InvalidCertificateException: Host appengine.google.com returned an invalid certificate
(_ssl.c:504: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed):
To learn more, see http://code.google.com/appengine/kb/general.html#rpcssl
というエラーが出て、deploy に失敗するという状態になってしまいました。
ネットで調べてみたところ、http://stackoverflow.com/questions/13899530/gae-sdk-1-7-4-and-invalidcertificateexception が出てきました。
cacerts.txt を削除するという対応が必要なようです。
$ cd /Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/cacerts
$ mv cacerts.txt{,.old}
としたところ、appcfg.py で deploy できるようになりました。
ラベル:GAE appcfg.py
posted by おちエン at 00:46| Comment(0) | GAE | このブログの読者になる | 更新情報をチェックする

2012年06月26日

fancybox で blobstore の画像を指定すると固まる件

GAE の blobstore に画像をアップロードして、その画像を fancybox で表示しようとしたところ、Safari だと完全に固まり、Chrome だと固まった後、辛抱強く待てば、画像のソース自体が表示されてしまうというとんでもない状態になってしまいました。

対応方法は
    $('a.fancy').fancybox({
        'type': 'image'
    });
とするだけ。
http://fancybox.net/faq の 6番。
ドキュメントはちゃんと読みましょうというのが今日の教訓。
ラベル:GAE javascript jquery
posted by おちエン at 23:32| Comment(0) | GAE | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は1年以上新しい記事の投稿がないブログに表示されております。