ラベル Google App Engine の投稿を表示しています。 すべての投稿を表示
ラベル Google App Engine の投稿を表示しています。 すべての投稿を表示

2010-12-29

Access-Control-Allow-Originをどこで出力すればよいのか迷ってみた

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
今まで、普通のjavaスクリプトで行える通信はjavaスクリプトを読み込んだサイトに対してだけだと思っていました。

以下の図でいうとAから読み込んだHTMLに書かれているjavaスクリプトでXMLHttpRequestを利用して通信できるのはAだけでBとは通信できないという感じです。
|-----|     |-----|
|  A  |     |  B  |
|-----|     |-----|
   |           |
   |           ×
|--------|     |
|ブラウザ|-----|
|--------|

でも、どうやらXMLHttpRequest level2というのではBとも通信できるようになるらしいです。
それもjavaスクリプトの記述の仕方では特に変わったことをする必要はなくAと通信するXMLHttpRequestと同じような書き方でよいそうです。
Bと通信できるようにするには、httpのヘッダーに
Access-Control-Allow-Origin
が出力されればOKとのことです。

で、ここでこのAccess-Control-Allow-Originヘッダを出力するのは、AなのかBなのかよくわからなくなってみましたが、結論としてはBの方でした。

ちなみにGoogle App EngineでAccess-Control-Allow-Originヘッダを出力するには、以下のような感じです。
self.response.headers['Access-Control-Allow-Origin'] = '*'

*の部分は接続を許容する先を記述するところで、*と書くとどこからでもOKということになります。

すべてのブラウザで対応しているわけではなさそうですが、javaスクリプトでできることが増えそうです。

2010-11-07

「図書ぶら」というのを作ってみました

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
図書館サイトの検索結果ページに、その本に関連する本のリストとAmazonへのリンクを追加するGreasemonkeyスクリプト「図書ぶら」というのを作ってみました。

私は、図書館をよく利用しています。
探す本がわかっているときはいいのですが、なんとなく本を探したいというときには、図書館サイトはむかないつくりになっています。
amazonさんの場合は本に関連する本を紹介してくれるので、参考にしちゃっています。
なのでそのamazonさんの関連本を図書館サイトの方にも表示させるようにしたら便利かもしれないと思い作ってみたのが「図書ぶら」です。

図書館で本を使う方は使ってみていただけるとうれしいです。

現在は、東京23区だけの対応になっていますがご要望があれば他の図書館にも対応したいと思っています。

ちなみに関連本を表示するためには、
Amazon Product Advertising API
を使っています。
その関連本が、その図書館に存在するかを調べるために
カーリル | 図書館API仕様書
を使っています。
これらのAPIはGoogleAppEngine上に作成したアプリがProxyして要求をかけています。
以下のような感じです。
図書ぶら-->GoogleAppEngine-->Amazon,カーリル

2010-10-08

Google App Engineのwebappでステータス404を返す

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
python版のGoogle App Engineで提供されているフレームワークであるwebappでhttpのステータスコード404を返したいなぁと思って調べたら、
class AaaPage(webapp.RequestHandler):
  def get(self):
    self.error(404)
    return self.response.out.write('404 not found')
というパターンと
class AaaPage(webapp.RequestHandler):
  def get(self):
    self.response.set_status(404)
    return self.response.out.write('404 not found')
という二つのパターンが見つかります。

何が違うのかしらん?と思っていたらgoogleさんに普通に書いてありました。
http://code.google.com/intl/ja/appengine/docs/python/tools/webapp/requesthandlerclass.html#RequestHandler_error

self.error(code)

self.response.clear()

self.response.set_status(code)
を呼び出した場合と同じだそうです。

なので違いは、
self.response.clear()
を呼ぶか呼ばないかみたいです。
self.response.clear()
を呼ぶ場合と呼ばない場合でどんな違いがあるのかよくわからんので
とりあえず呼んでおくことにして
self.error(code)
を使うことにしてみました。

2010-09-08

Google App EngineでPORTAのAPIを使ってみようと思ったけど・・・

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
PORTAとは、国立国会図書館デジタルアーカイブポータルです。
こちらがAPIを提供してくれており、詳しくは以下を見てください。
http://porta.ndl.go.jp/wiki/Wiki.jsp?page=%E5%A4%96%E9%83%A8%E6%8F%90%E4%BE%9B%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

PORTAを使うとamazonとは違う感じの情報が取れないかなぁと思いGoogle App Engine(の開発環境)でAPIを試してみたところ、残念ながらタイムアウトになってしまいデータが取れなかったのです。

試したプロトコルは、OpenSearchです。
これが帰ってくる情報に結構いろいろのっている感じでよさげだったもので。
ちなみにISBNで検索するならば以下のような感じです。
http://api.porta.ndl.go.jp/servicedp/opensearch?isbn=9784334975586
戻りデータは、RSSですが拡張していろんな情報がのっています。

やろうとしたことは、図書館の分類方法のNDC(日本十進分類法)でデータを検索です。
こちらで検索するとなんかISBNとかがのってないような資料もいっぱいひっかかってしまいました。
比較的ISBNが付いているようなデータが戻ってくるようにするには、ジャンルを限定すればよい感じでした。これでもすべてのデータにISBNが付いているわけではありませんでしたが。

ちなみに試したのは、以下のような感じです。
NDCが588で始まるもの一覧です。
ジャンル指定は、dpidで指定しますがzomokuを指定するとよい感じでした。
http://api.porta.ndl.go.jp/servicedp/opensearch?ndc=588&dpid=zomoku

ちなみにndcは、588.xxxみたいに.以下も付いたりするのですがndcで指定できるのは先頭3桁までのようです。

もうちょっといじってみたかったけど、Google App Engineでタイムアウトといわれてしまうとイカんともしがたい気がするので、とりあえず断念してみる。

2010-05-13

Googleドキュメントにあるドキュメントをランダムで取得してメールをする

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Googleドキュメントにいろいろメモを残しているのに全然見返すことをしていないない・・・
そんな私のためにGoogle App EngineでGoogleドキュメントの内容をランダムで取得してメール送信するものを作ってみました。

機能としては、
・文章のみをメール送信します。スプレッドシートなどは送信しません。
・取得対象はランダムです。
・文章を送信対象外にするリストを持ち、リストに追加したドキュメントは送信しません。
・oAuthを利用します
てな感じです。

エラー処理が少々大雑把なため
ドキュメントが一つもなかったり、すごく大量にあった場合にどうなるかはわかりません。

Djangoのアプリケーションになっています。
http://docs.google.com/leaf?id=0BydytAINVs9VM2E5NWRlMGItNWM1Yy00OTZhLWI5MTctYjQ0MDliNWJhMjI0&hl=ja
にアプリ部分だけzipしたものを置いてみましたので、もしご興味があればご利用ください。
zipを解凍してできたディレクトリをDjangoプロジェクトのルートに配置して利用できるように設定します。
ディレクトリ内のsettings.pyは編集する必要があります。

実行には、gdataが必要です。
以下から取得できます。
http://code.google.com/p/gdata-python-client/

Google App Engine patchも必要な気がします。
こちらで利用しているモジュールも使っているような気がします。
以下から取得できます。
http://code.google.com/p/app-engine-patch

app.yamlには
- url: /gdoc_sender/.*
  script: common/appenginepatch/main.py
  login: admin
みたいなエントリを追加する必要があります。

あと、queue.yamlを以下のような感じで。
queue:
- name: default
  rate: 5/m

- name: gdoc-sender
  rate: 5/m

そして、cron.yamlを以下のような感じで。
cron:
- description: daily mail send
  url: /gdoc_sender/set_queue/
  schedule: every day of month 09:00
  timezone: Asia/Tokyo

こんなメモを残していたのか・・・
と毎日一つは残したメモを見返すようになりましたとさ。

2010-05-09

Google App Engineのタスクキューのメモ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google App Engineのタスクキューを利用したときのメモです。
Pythonさんの場合です。

defaultのキューではなくて、独自名称のキューを用意して利用する方法は、以下のリンク先を参考になります。
http://mitsukuni.org/blog/2010/01/07/appengineでqueueを分ける/
ちなみに独自で定義したキュー名にはアンダーバー(_)とかは使えません。
使えるのは英数字とハイフン(-)だけっぽいです。
使えない名前で定義してもエラーで教えてくれますけどね。

あと、ローカルの開発環境でテストするには一度アプリケーションでadminユーザとしてログインしておかないと403エラーになってキューのテストができません。
テスト環境でユーザログインの際に
Sign in as Administrator
にチェックを入れ忘れて、しばらく悩んでみました。
app.yamlでキューのurlをadmin指定でなくせばダイジョブなのかもしれませんが。

ちなみにcronの設定もadminユーザでログインしていないとダメでした。

2010-05-04

googleドキュメントで作成した文章をAPIを利用してテキストで取得する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
googleドキュメントで作成した文章をGoogle App Engineで取り出したくなりました。
Google App Engineで簡単に利用したいのでtext形式でダウンロードがしかくなったのです。

以下のような感じで取れました。
Djangoでの例です。
とりあえず前件取得してランダムで取得してみます。
# -*- coding: utf-8 -*-
import random
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _
from ragendja.template import render_to_response
from django.conf import settings
import gdata.gauth
import gdata.docs.client
import gdata.docs.data

APP_NAME = 'googleDocumentTextGetTest'
def index(request):
  payload = dict()
  client = gdata.docs.client.DocsClient(source=APP_NAME)
  client.ssl = True
  client.ClientLogin('googleアカウントのメールアドレス', 'そのパスワード', client.source)
  payload['feed'] = client.get_everything()
  feed_len = len(payload['feed'])
  while True:
    get_doc = random.randint(0, feed_len-1)
    payload['selection'] = payload['feed'][get_doc]
    #取れたものがスプレッドシートとかだったらもう一回取り直す
    doc_type = payload['selection'].GetDocumentType()
    if doc_type == "document":
      break
  doc_uri = '/feeds/download/documents/Export?docID=' + payload['selection'].resource_id.text + '&exportFormat=txt'
  payload['content'] = client.get_file_content(doc_uri)
  return render_to_response(request, 'index.html',payload)


参考までにテンプレートは以下のような感じです。
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
dir="{% if LANGUAGE_BIDI %}rtl{% else %}ltr{% endif %}"
xml:lang="{% firstof LANGUAGE_CODE 'en' %}"
lang="{% firstof LANGUAGE_CODE 'en' %}">
<head>
<title>test</title>
</head>
<body>
{{ selection.title.text }}<br>
<pre>
{{ content }}
</pre>
<ul>
{% for entry in feed.entry %}
<li>{{ entry.title.text }}</li>
{% endfor %}
</ul>
<body>
<html>  


本当だったら、全件取得でなく以下のような感じで
/feeds/default/private/full/-/document
documentファイルだけを取得したかったのですが、なぜかできませんでした。

2010-05-02

GAEでgoogleさんにOAuth

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google App EngineでgoogleさんにOAuthしてみました。
Djangoを使ったpythonで実験しています。

まずは準備としてGoogleさんにサイトを登録して
Consumer Key

Consumer Secret
を手に入れる必要があります。

https://www.google.com/accounts/ManageDomains
で利用ドメインを登録します。すると
Manage registration
に登録したドメインが出るのでクリックします。
最初に登録したドメインのページにメタタグを埋め込んでサイトの確認を実行します。
すると
Target URL path prefix:
を入れる欄が出てくるようになるので
とりあえず
サイトでOAuthを利用するパスを入れてセーブします。
例:
 http://xxxx.xxxx.xxxx/oauth_test/index.html
 とかでOAuthを使ったもろもろをoauth_test配下に入れて置くならば、
 http://xxxx.xxxx.xxxx/oauth_test
 を登録します。
(実際は、どんなものを入れるのがよいのかいまいちよく分かっていません)

これで
Consumer Key

Consumer Secret
が発行されるのでメモしておきましょう。

今回OAuth関連の処理をするものとしてgdataを利用します。
http://code.google.com/p/gdata-python-client/
gdataは、OAuth用というよりもGoogleカレンダーとかドキュメントとかのAPIを扱う便利クライアントです。
OAuthしたらなんらかのgoogleのAPIを利用するのでこれを利用します。
取得したら、
Djangoプロジェクトディレクトリ直下に
atom
gdata
をコピーします。

今回、OAuthを試すアプリとして
oauth_test
を作ります。
これはgoogleドキュメントに登録してあるデータ一覧を取得するものにしてみます。
なのでsettings.pyに使えるように設定しておきます。
またoauth_testでは認証がかかるようにapp.yamlに以下を追加します。

- url: /oauth_test/.*
script: common/appenginepatch/main.py
login: required

なので今回用意したものは以下のような感じです
Djangoルート
|-atom
|-gdata
|-oauth_test
|-template
| |-index.html
|-settings.py
|-urls.py
|-urlsauto.py
|-views.py

oauth_test配下のものはざっと以下のような感じです。

settigns.py

from ragendja.settings_post import settings
settings.CONSUMER_KEY = '取得したConsumer Keyを入れます'
settings.CONSUMER_SECRET = '取得したConsumer Secretを入れます'


urlsauto.py

# -*- coding: utf-8 -*-
from django.conf.urls.defaults import *
rootpatterns = patterns('',
(r'^oauth_test/', include('oauth_test.urls')),)


urls.py

# -*- coding: utf-8 -*-
from django.conf.urls.defaults import *
urlpatterns = patterns('oauth_test.views',
(r'^$', 'index'),
(r'^oauth_set/$', 'oauth_set'),
(r'^oauth_callback/$', 'oauth_callback'),
(r'^oauth_revork/$', 'oauth_revork'),
)


view.py

# -*- coding: utf-8 -*-
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _
from ragendja.template import render_to_response
from django.conf import settings
from google.appengine.api import users

import gdata.gauth
import gdata.docs.client
import gdata.docs.data

APP_NAME = 'oauthMyTest'
def index(request):
payload = dict()
login = users.get_current_user()
#すでに登録済みかどうかを確認します
#gdata.gauth.Ae*を利用することでGoogle App Engineのデータストアに
#取得したOAuthのトークンとシークレットをオブジェクトして格納して出し入れできます。
#memcacheのようにキーとtokenがセットになっています。
#ここではログインユーザのuser_idをキーにしています。
token = gdata.gauth.AeLoad(login.user_id())
if token == None:
payload['have_token'] = False
else:
payload['have_token'] = True
#ドキュメント一覧を取得します
#client.ssl = Trueを必ずつけましょう
#付け忘れるとInvalid Tokenとか言われて悩みます
client = gdata.docs.client.DocsClient(source=APP_NAME)
client.ssl = True
client.auth_token = gdata.gauth.AeLoad(login.user_id())
payload['feed'] = client.get_doclist()
return render_to_response(request, 'oauth_test/index.html',payload)

def oauth_set(request):
#googleにリダイレクト処理をします
SCOPES = ['https://docs.google.com/feeds/']
callback_url = 'http://%s/oauth_test/oauth_callback/' % request.get_host()
client = gdata.docs.client.DocsClient(source=APP_NAME)
request_token = client.GetOAuthToken(SCOPES, callback_url, settings.CONSUMER_KEY, consumer_secret=settings.CONSUMER_SECRET)
login = users.get_current_user()
#callbackしてきたときに利用できるように一時的にtokenを格納します。
gdata.gauth.AeSave(request_token, "tmp_" + login.user_id())
return HttpResponseRedirect(request_token.generate_authorization_url())

def oauth_callback(request):
#アクセス用のトークンとトークンシークレットを格納します
login = users.get_current_user()
#一時的に格納したtokenを取り出し削除しておきます。
saved_request_token = gdata.gauth.AeLoad("tmp_" + login.user_id())
gdata.gauth.AeDelete("tmp_" + login.user_id())
request_token = gdata.gauth.AuthorizeRequestToken(saved_request_token, request.build_absolute_uri())
client = gdata.docs.client.DocsClient(source=APP_NAME)
try:
#ここでアクセストークンを取得して格納
access_token = client.GetAccessToken(request_token)
gdata.gauth.AeSave(access_token, login.user_id())
except:
logging.info('cant get access token')
return HttpResponseRedirect('/oauth_test/')

def oauth_revork(request):
#取得したtokenを破棄します
login = users.get_current_user()
gdata.gauth.AeDelete(login.user_id())
return HttpResponseRedirect('/oauth_test/')


template/index.html

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
dir="{% if LANGUAGE_BIDI %}rtl{% else %}ltr{% endif %}"
xml:lang="{% firstof LANGUAGE_CODE 'en' %}"
lang="{% firstof LANGUAGE_CODE 'en' %}">
<head>
<title>oauth_test</title>
</head>
<body>
{% if have_token %}
<a href="/oauth_test/oauth_set/">登録する</a>
{% else %}
<ul>
{% for entry in feed.entry %}
<li>{{ entry.title.text }}</li>
{% endfor %}
</ul>
<hr>
<a href="/oauth_test/oauth_revork/">登録を解除する</a>
{% endif %}
</body>
</html>


こんな感じです。
TwitterのOAuthと比べるとちょっとめんどっちい感じです。

2010-04-26

google app engine patchでアプリ内に独自設定値を定義して利用する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
google app engine patchでアプリ内で独自の設定を定義して利用する方法です

通常
root
|-myapp
|-settings.py ← ここに設定値とかを書くわけですが、
ここだとグローバルな設定値な感じなので
myapp内だけで利用するような設定値を定義したい場合です。

myapp内にもsettings.pyを用意します。
root
|-myapp
| |-settings.py
|-settings.py

この自アプリ内のsettings.pyを以下のように書きます。

from ragendja.settings_post import settings
settings.MY_TEST = 'test test'

で使う時には、以下のような感じです。

from django.conf import settings

def index(request):
mytest = settings.MY_TEST

2010-04-18

Google App EngineからTwitterにつぶやく

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google App EngineからTwitterにつぶやく方法です。

まず用意するのは、
TwitterのOauthサイトに飛ぶための機能
TwitterのOauthからCallbackされるところ
が必要です。

これがつぶやくための情報が取得できたことになるので
これではじめてつぶやけます。

まずTwitterのAPIを利用するための登録をTwitterに行います。
http://www.msng.info/archives/2010/01/twitter_api_oauth_with_php.php
がとても参考になります。

そしてGoogle App EngineからTwitterのAPIを利用するには、
AppEngine-OAuth-Library
が大変便利です。
使い方は、
http://blog.mudaimemo.com/2010/02/google-app-engine-twitter-oauth.html
が大変参考になります。

ざっくり使うならば以下のような感じになります。
# -*- coding: utf_8 -*-

import os
import sys
import logging

from google.appengine.ext.webapp import template
from google.appengine.ext import webapp
from google.appengine.api import urlfetch
from django.utils import simplejson as json
import traceback
import urllib
#AppEngine-OAuth-Libraryを読み込みます。
import oauth

import wsgiref.handlers

#登録した値を使います
CONSUMER_KEY = 'アプリのConsumer key'
CONSUMER_SECRET = 'アプリのConsumer secret'

class Top(webapp.RequestHandler):
  def get(self):
    template_values = {}
    path = os.path.join(os.path.dirname(__file__), 'top.html')
    self.response.out.write(template.render(path, template_values))

class TwitSignin(webapp.RequestHandler):
  def get(self):
        callback_url = '%s/twitter/callback' % (request.host_url)
        client = oauth.TwitterClient(CONSUMER_KEY, CONSUMER_SECRET,callback_url)
        self.redirect(client.get_authorization_url())

class TwitCallback(webapp.RequestHandler):
  def get(self):
    #つぶやくために必要なのは以下の二つではありません
    token = request.get('oauth_token')
    verifier = request.get('oauth_verifier')
    client = oauth.TwitterClient(CONSUMER_KEY, CONSUMER_SECRET,None)
    #以下の部分で肝心な情報を取得します
    user_info = client.get_user_info(token, verifier)
    #この下で取得する2つの情報がつぶやくために必要になります
    oauth_token  = user_info['token']
    oauth_secret = user_info['secret']

    #重要な情報がとれたところでついでにつぶやきサンプルです。
    msg = "oauthテスト なう"
    additional_params = {'status': msg}
    try:
        response = client.make_request('http://twitter.com/statuses/update.json',
                                       token=oauth_token,
                                       secret=oauth_secret,
                                       additional_params=additional_params,
                                       protected=True,
                                       method='POST')
        data = json.loads(response.content)
        if data.has_key('error'):
            logging.error(data['error'])
    except Exception, e:
        logging.error(traceback.format_exc())
        
    self.redirect("/")


def main():
  application = webapp.WSGIApplication([
                                        ('/', Top),
                                        ('/twitter/signin', TwitSignin),
                                        ('/twitter/callback', TwitCallback),
                                        ],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
  main()

ちなみにtop.htmlは
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>test</title>
</head>
<body>
<a href="/twitter/signin">auth twitter</a>
</body>
</html>

2010-04-14

Google App Engineで短縮URLのAPIを利用する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
最近、よく見る短縮URLをGoogle App Engineでも利用してみます。
bit.lyは、APIを利用できるのでbit.lyを使うことにします。

利用のためには、以下でアカウント登録が必要ですが無料ですし必要なのはメールアドレスだけです。
http://bit.ly/account/register
登録が済んだら以下でApiKeyを取得します。
http://bit.ly/account/your_api_key

ここまで出来たら準備OK。

以下のような関数を作って呼び出せば、短縮urlを利用できます。
# -*- coding: utf_8 -*-

from google.appengine.api import urlfetch
import urllib

def make_short_url(url):
    bitly_account = "bit.lyに登録したアカウント"
    bitly_key     = "bit.lyから発行されたAPIキー"
    bitly = "http://api.bit.ly/v3/shorten"
    bitly = bitly + "?login=" + bitly_account + "&apiKey=" + bitly_key
    bitly = bitly + "&format=txt"
    bitly = bitly + "&longUrl=" + urllib.quote_plus(url)
    result = urlfetch.fetch(bitly)
    if result.status_code != 200:
        return None
    return result.content[:-1]

2009-07-22

jQueryでcookieを

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
jQueryを使うといろいろステキなわけですが、cookieの取り扱いもステキです。
利用方法は、
http://blog.4galaxy.net/28.html
を見ていただければ完璧です。

ちなみにGoogle App EngineでDjangoを使うときに便利なapp engine patchを利用しているとjQuery関連が一つにまとめられているのでcookieマネージャであるjquery.cookie.jsも同じ場所においておくことにします。

場所は、
プロジェクトルート/common/jquery/media
において
プロジェクトルート/common/jquery/settings.py
を以下のようにjquery.cookie.jsを追加します。

from ragendja.settings_post import settings
settings.add_app_media('combined-%(LANGUAGE_CODE)s.js',
'jquery/jquery.js',
'jquery/jquery.fixes.js',
'jquery/jquery.ajax-queue.js',
'jquery/jquery.bgiframe.js',
'jquery/jquery.livequery.js',
'jquery/jquery.form.js',
#追加しました
'jquery/jquery.cookie.js',
)

これでcookieが簡単に使えちゃいます。

以下のような感じです。

#セット
$.cookie('attr','val',{ expires: 30 });
#ゲット
test = $.cookie('attr');

2009-07-21

google app engine pathではjQueryが組み込まれている

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google App EngineでDjangoを使うためにpatchを利用しているわけですが、settings.pyの中の
INSTALLED_APPSにjqeuryとか書いてあったのです。

INSTALLED_APPS = (
# Add jquery support (app is in "common" folder). This automatically
# adds jquery to your COMBINE_MEDIA['combined-%(LANGUAGE_CODE)s.js']
# Note: the order of your INSTALLED_APPS specifies the order in which
# your app-specific media files get combined, so jquery should normally
# come first.
'jquery',
・・・
)

これを書いておけばmediautilsでまとめあげたjavaスクリプトを読み込んでおけばjqueryも使えてしまうということなのでした。
具体的に利用できるものとしては、
プロジェクトルート/common/jquery/settings.py
に書いてありますが、以下のものが利用できるようです。
jquery.js
jquery.fixes.js
jquery.ajax-queue.js
jquery.bgiframe.js
jquery.livequery.js
jquery.form.js

jQueryも使おうかと思ったので、このjqueryのエントリも残しておくことにしました。

2009-07-20

google app engine patchのmediautils

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
google app engine patchにはmediautilsなるものが利用できるようです。
内容的には、
http://code.google.com/p/app-engine-patch/wiki/MediaGenerator
を見るのが一番なのですが、用は自分の作ったアプリケーションで利用するjavaスクリプトやCSSを一つのファイルにまとめて圧縮してくれるというもののようです。

mediautilsは最初の設定から利用できるようになっています。
関係するsettings.pyの内容は以下の部分のようです。
実際にはちょっと自分で買えている部分はあります。

LANGUAGE_CODE = 'ja'

LANGUAGES = (
('ja', 'Japanese'),
('en', 'English'),
)

#ここに書かれているファイルにまとめられるようです。
#ここに纏め上げるjavaスクリプトやcssを書くようです。
COMBINE_MEDIA = {
'combined-%(LANGUAGE_CODE)s.js': (
'.site_data.js',
),
'combined-%(LANGUAGE_DIR)s.css': (
'global/look.css',
),
}

MEDIA_VERSION = 1

INSTALLED_APPS = (
# ...
'mediautils',
# ...
)


テンプレートでは、

<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}combined-{% if LANGUAGE_BIDI %}rtl{% else %}ltr{% endif %}.css" />
<script type="text/javascript" src="{{ MEDIA_URL }}combined-{{ LANGUAGE_CODE }}.js"></script>

と指定して利用するようです。

追加するファイルは、プロジェクトのsettings.pyにすべて書いておいてよいのですが、各アプリケーションで個別に追加することもできるようです。
追加するjsファイルをアプリケーションのディレクトリの下にmediaというディレクトリを作って、さらにアプリケーションのディレクトリにsettings.pyを作って以下のような感じに書けばよいみたいです。

from ragendja.settings_post import settings
settings.add_app_media('combined-%(LANGUAGE_CODE)s.js',
'myapp/code.js',
)


いまいち便利さがよくわかっていないのですが、サンプルでも使っているしpatchをいろいろ使うには利用した方がよさそうな気もするので、とりあえずmediautilsは使っていってみようかと思います。

Google App Engine patchを利用している時にテンプレートでMEDIA_URLが取得できなかった

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
google app engine patchを利用して遊んでいます。
画像をおいて参照しようと思ったのです。
デフォルトの設定そのままな感じでは
/media
の下に画像をおいて
テンプレートで
<img src="{{ MEDIA_URL }}global/logo.png" alt="" />
と書いておけば利用できるようにサンプルを見るとできそうなので自分の作ったアプリでも試してみたのですが、最初は{{ MEDIA_URL }}を解決してくれませんでした。
そしてサンプルではちゃんと解決してくれるわけです。

これは、views.pyで
from django.shortcuts import render_to_response
としていたのがいけなくて
from ragendja.template import render_to_response
としないといけなかったようです。

そしてこの変更をしたら
render_to_responseを使い方も変更が必要でした。
requestを渡してあげる必要があるようです。
以下のような感じです。

def index(request):
payload = dict()
payload['test'] = 'testtest'
#変更前のコード
# return render_to_response('test_index.html', payload)
#変更後のコード
return render_to_response(request,'test_index.html',payload)

2009-07-06

Google App EngineでDjangoは、helperからpatchにしてみた

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
http://kingyo-bachi.blogspot.com/2009/06/google-app-enginedjango.html
でGoogle App EngineでDjangoを利用するには、Google App Engine Helperが便利と書いてみましたが、
manage.py test
を実行するとGoogle App Engine Helperのテストエラーが出てしまいました。
私の環境がwindowsであることが原因な気がしつつ、そしてどっかいい感じにパスを通せばなんとかなるような気がしたりしつつ調べていたら
Google App Engine patch
という方がいい感じな気配なので切り替えました。

Google App Engine patchでは、Djangoの機能をGoogle App Engine上で使えるものが多くなっています。

Google App Engine patchは
http://code.google.com/p/app-engine-patch
から取得できます。
こちらからダウンロードしたものを解凍すれば、そのままサンプルになっています。

Google App Engine patchには、Djangoの1.0系のzipファイルも含まれているので自分でDjangoのzipファイルを準備する必要はありません。

もちろん
manage.py test
でエラーはでません。
ですが、windowsの環境でsettings.pyで
USE_I18N = True
となっていると
manage.py runserver
としたときに、gettextのワーニングがいろいろ出ます。
これを解消するには、
http://docs.djangoproject.com/en/dev/topics/i18n/#gettext-on-windows
から
gettext-runtime-0.17-1.zip
gettext-tools-0.17.zip
を取得して、それぞれを解凍して出来たディレクトリの中身を
C:\Program Files\gettext-utils
に入れます。
そして環境変数PATHに
C:\Program Files\gettext-utils\bin
を通すことでワーニングは解消されます。
単に設定を
USE_I18N = False
にするのでも差し支えはないとは思います。

これでDjangoのadmin画面とかが使えちゃえます。
かなり便利です。
デフォルトだと独自にadminアカウントを作って、そのアカウントでログインするようになっていますが、Google App Engineを使っているならば、そこいら辺はGoogleアカウントにお任せしたいところです。
その手段は、
http://code.google.com/p/app-engine-patch/wiki/GoogleAccounts
に書いてありました。

私は、以下のような感じにしてみました。
app.yamlに

- url: /admin/.*
script: common/appenginepatch/main.py
login: admin

として、
settings.pyのmiddlewareの部分を
'django.contrib.auth.middleware.AuthenticationMiddleware'
をコメントアウトして
'ragendja.auth.middleware.GoogleAuthenticationMiddleware'
を有効にします。
そして
AUTH_USER_MODULE = 'ragendja.auth.google_models'
AUTH_ADMIN_MODULE = 'ragendja.auth.google_admin'
も有効にします。
これで/adminにアクセスすればgoogleアカウントのログイン画面が表示されて、admin権限があるユーザのみが利用できるようになります。

そして自分が作ったアプリケーションのmodelをadminで利用するには以下のような感じです。
ここではアプリケーション名をahahaでmodels.pyにOhohoというクラスを作ったとします。
もちろんsettings.pyには記述済みというコトで。
Ohohoをadmin画面で管理できるようにするには、
ahahaディレクトリに以下のようなadmin.pyを作成します。

from ahaha.models import Ohoho
from django.contrib import admin

admin.site.register(Ohoho)

これだけです。

2009-06-27

Djangoのローカルテスト環境でGoogle map apiを利用する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google map APIを利用するには、サイトのurlが必要になります。

本番環境は、問題ないとしてローカルでテストしているときですが、Djangoの場合
http://localhost:8000
となっているわけです。

ここでテストするにはどうしたらよいかと思っていたら
普通にGoogle map APIのkeyの申請のところで
http://localhost:8000
と申請すればよいだけでした。

で、Google App EngineのDjango環境でためしに住所から緯度経度を取ってみるサンプルです。
まずsettings.pyに
MAP_KEY = 'xxxxxxxxx'
と定義しておきます。

適当なところで以下のような感じで

# -*- coding: utf-8; -*-

from django.conf import settings
import xml.etree.ElementTree as etree
from google.appengine.api import urlfetch
import urllib

def test_gmap():
url = 'http://maps.google.com/maps/geo?'
url = url + 'key=' + settings.MAP_KEY
url = url + '&sensor=false'
url = url + '&output=xml'
url = url + '&q=' + urllib.quote('千代田区丸の内1-9-1')
result = urlfetch.fetch(url)

if result.status_code == 200:
dom = etree.fromstring(result.content)
namespace ='http://earth.google.com/kml/2.0'
retunrn dom.findtext('.//{%s}coordinates' % namespace)


ちょっとはまったポイントとしては、日本語を利用するならばファイルの先頭に
# -*- coding: utf-8; -*-
を忘れずに。
manage.py startapp
で生成するviews.pyとかにはcodingが入っていないので入れ忘れていてエラーが出てちょっと考えちゃいました。

あと、xmlの解析に利用しているElementTreeについては、
http://python.matrix.jp/modules/ElementTree.html
が参考になります。

2009-06-19

Google App EngineのDjangoでチュートリアルをやってみる

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google App Engine上のDjangoは、使えるデータベースが特殊なため以下のDjangoのマニュアルにあるチュートリアルはそのままではできないようです。
http://djangoproject.jp/doc/ja/1.0/index.html

なのでGoogle App Engine上のDjangoでのチュートリアルが
http://webos-goodies.jp/archives/51337216.html
にあるので、こちらを参考にしたわけですがそのままでは動きませんでした。
私の作成した環境が
Google App EngineでDjangoを利用する
で紹介させていただいたように、Djangoは1.0.2を利用していて更にGoogle App Engine Helperを利用している環境のためだろうと思います。

というわけで私の環境で
http://webos-goodies.jp/archives/51337216.html
で紹介してあるチュートリアルを動くようするための変更点を紹介させていただきます。

まずhelperを入れているので
python manage.py startapp poll
の前まではすでに準備が出来ているので何もしません。

settings.pyのINSTALLED_APPSだけを以下のように変更します:

INSTALLED_APPS = (
'appengine_django',
'poll',
)


url.pyは、以下のように変更します。

from django.conf.urls.defaults import *

urlpatterns = patterns('poll.views',
(r'^$', 'index'),
(r'^create/$', 'create'),
(r'^poll/(?P[^\.^/]+)/$', 'poll_detail'),
(r'^poll/(?P[^\.^/]+)/results/$', 'poll_results'),
)


models.pyは紹介しているままです。

bforms.pyは、以下のようにします。
formsのimportとcleaned_dataの部分を修正しています。
このファイルは、pollディレクトリに作成します。

from django import forms
import models
from google.appengine.ext.db import djangoforms

class PollForm(djangoforms.ModelForm):
class Meta:
model = models.Poll
exclude = ['created_by']

class ChoiceForm(forms.Form):
choice = forms.CharField(max_length = 100)

def __init__(self, poll=None, *args, **kwargs):
self.poll = poll
super(ChoiceForm, self).__init__(*args, **kwargs)

def save(self):
choice = models.Choice(poll = self.poll, choice = self.cleaned_data['choice'])
choice.put()


views.pyは、
from pollango.poll import models
となっているものを
from poll import models
に直すだけです。

後は、http://webos-goodies.jp/archives/51337216.htmlに書いてある通りで動くようになりました。

2009-06-14

Google App EngineでDjangoを利用する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google App Engine for javaを勉強しようかなぁと思っていましたが、気が変わりDjangoの方を勉強してみようと思い立ったのです。

ちなみに開発環境はwindowsです。

Google App Engineには、0.96.1のDnangoが
C:\Program Files\Google\google_appengine\lib\django
にあったりして、そのまま利用できるバージョンはこのバージョンのようですが、
最新は、1.0.2のようです。
なので、この1.0.2が利用できてeclipseで開発できる環境までを構築してみました。

pythonはインストール済みなのが前提です。

最初に、Djangoをインストールします。
http://www.djangoproject.com/download/
から
Django-1.0.2-final.tar.gz
を取得して解凍します。
コマンドプロンプトで解凍したディレクトリの中の
Django-1.0.2-finalのディレクトリに移動して
python setup.py install
を実行します。

更にこのディレクトリ内のdjangoディレクトリをzip圧縮したdjango.zipを作っておきます。

Djangoが正しくインストールできたことを確認するためにコマンドプロンプトで
C:\Python25\Lib\site-packages\django\bin\django-admin.py --version
(PythonがPython25にインストールされている場合です)
を実行して
1.0.2 final
と表示されることを確認します。

Google App EngineをDjangoを利用するには、
Google App Engine Helperを利用すると便利なようなので利用します。
http://code.google.com/p/google-app-engine-django/downloads/detail?name=appengine_helper_for_django-r86.zip&can=2&q=
から
appengine_helper_for_django-r86.zip
を取得して解凍します。

Djangoでは、プロジェクトという単位が一番大きな管理単位のようです。
そのプロジェクトを作成します。
ここではC:\temp\pythonとします。
プロジェクトのためのディレクトリを作成します。
ここでは
test_django
とします。

このディレクトリに
helperのzipを解凍してできたディレクトリの中身をコピーします。
また、このディレクトリを事前に作っておいたzip圧縮して作成したdjango.zipもコピーします。

helperをwindowsで利用するには、
http://sourceforge.net/projects/pywin32
にある
pywin32-212.win32-py2.5.exe
を取得してインストールしておく必要があるようです。
(参考:http://code.google.com/intl/ja/appengine/articles/appengine_helper_for_django.html

helperが動作することを確認します。
コマンドプロンプトでDjangoプロジェクトのディレクトリに移動します。
cd C:\temp\python\test_django
Djangoのサーバーを起動します。
python manage.py runserver
そして
http://localhost:8000
にアクセスしてDjangoのページが表示されることを確認します。
また、
http://localhost:8000/_ah/admin
で、Google App Engineのadminページも利用できることも確認します。

ここまでの内容は、
http://code.google.com/intl/ja/appengine/articles/appengine_helper_for_django.html
http://mars.shehas.net/~tmatsuo/misc/appengine_helper_for_django-ja.html
が参考になります。

次にeclipseで作成したDjangoプロジェクトを開発できるようにします。
私はEclipseは3.3を利用しています。
そしてPythonが開発できるためのPydevはインストール済みのものとします。

eclipseを起動して
「ファイル」-「新規」-「プロジェクト」を選択
「Pydevプロジェクト」を選んで「次へ」
djangoプロジェクトを作成したディレクトリを
プロジェクト・コンテンツのディレクトリーに指定
(ここではC:\temp\python\test_django)
プロジェクト名を作成したdjangoプロジェクトと同じにする
(ここではtest_django)
デフォルトのsrc・・・のチェックをはずす
そして「完了」
これでeclipseでDjangoプロジェクトが見れるようになります。

次に、manage.pyでrunserverが動作するようにします。

作成されたプロジェクト名を右クリック
「プロパティ」を選択
「Pydev」-「PYTHONPATH」-「Project source folder」-「ソースフォルダの追加」
でプロジェクトのディレクトリを指定する
(ここではtest_django)

manage.pyを右クリックして
「実行」-「実行ダイアログを開く」
「Python実行」を右クリックして「新規」を選択
 「プロジェクト」にdjangoプロジェクトを選ぶ(ここではtest_django)
 「メイン・モジュール」にmanage.pyを選ぶ
「引数タブ」をクリックして
 「program argument」にrunserverを記述し
 「作業ディレクトリ」-「その他」を選択してワークスペースをクリックしてプロジェクトのルートを選択する(ここではtest_django)
そして「実行」をクリックするとhttp://localhost:8000で最初に確認したdjangoのページが見れるようになります。

ちなみに
python.exe manage.py startapp polls
のようにプロジェクトの下に新しいファイルをコマンドプロンプトで追加した場合、
eclipse上でプロジェクトを右クリックして「更新」をすると新しく作成されたファイルが見えるようになります。

こんな感じでは、まずは開発環境を作ってみました。


*最初は、0.96.1でやろうとしましたが、helperの最新版では1.0以上が必要で、更に0.96に対応しているr52では、Google App Engineのバージョンが新しいとなんかうまく使えなかったので使うのをやめました。新しいVersionが使えることに越したことはないですしね。

2009-05-30

Google App Engineの一つのアプリケーションでいろいろ実験する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google App Engineは、無料で使えるのは10個のアプリケーションなわけです。
ある実験サイトを作ろうと思ったときに、localだけでは実験しきれないことがどうしてもあります。
たとえば、iアプリとかと連携したサイトで実際に端末にダウンロードして実験したいときなどはデプロイするしかありません。

でも、あくまでも実験なので実験のたびに貴重なアプリケーションを浪費するわけにはいかないなぁと思っていたのです。

実験用のものを一つ用意して、その一つを使い回せばいいのですが、上書きすると消えちゃうので、それはそれで困ることもあるかも。と思っていたのです。

ですが、残しておきたければversionを変えておけばよいだけということを
http://www.atmarkit.co.jp/fjava/rensai4/gaej01/gaej01_4.html#08
を見て今更ながらわかってみました。

アクセスできるのは、デフォルト設定されたversionのものだけのようですが、どうせ実験なので実験するときだけversionを変えればよいわけですね。

最近Google App Engineにはjavaも追加されたわけですが、一つのアプリケーションにversionを変えてjavaとpythonは共存できるようです。

なので今更ながら、実験用に一つアプリケーションを増やしてみました。