2008年6月30日月曜日

Model.get_or_insert(key_name, **kwds)

文字どうり、 get_or_insert する。
存在しなけれ r.put()  してくれる。
key_name は省略できない。 key_name は、先頭が数字は不可。
同時に実行されたら 2レコード作成されてしまうかもしれない。
r = Greeting.get_or_insert("Key001", Title="test",  xxx = xxx, .... )

Model.get_or_insert(key_name, **kwds)

Get or create an entity of the model's kind with the given key name, using a single transaction. The transaction ensures that if two users attempt to get-or-insert the entity with the given name simultaneously, then both users will have a model instance that refers to the entity, regardless of which process created it.

Arguments:

key_name
The name for the key of the entity
**kwds
Keyword arguments to pass to the model class if an instance with the specified key name doesn't exist. The parent argument is required if the desired entity has a parent.

The method returns an instance of the model class that represents the requested entity, whether it existed or was created by the method. As with all datastore operations, this method can raise a TransactionFailedError if the transaction could not be completed.

http://code.google.com/appengine/docs/datastore/modelclass.html#Model_get_or_insert

key_name は長いものはだめだったような気がしていたけれども、間違いだった。
ただ、やはり where 句の検索条件には利用できない。

A key_name is stored as a Unicode string (with str values converted as ASCII text). A key_name must not start with a number.

Tip: Key names and IDs cannot be used like property values in queries. However, you can use a named key, then store the name as a property. You could do something similar with numeric IDs by storing the object to assign the ID, getting the ID value using obj.key().id(), setting the property with the ID, then storing the object again.

http://code.google.com/appengine/docs/datastore/keysandentitygroups.html



親に子を追加

p = db.GqlQuery("select * from Oya_model")[0]
r = Ko_model.get_or_insert("Key001",parent=p,att1=200801,...)

子から親を検索 親が見つかったら、その kind と key を表示

pp = db.GqlQuery("select * from Ko_Model")
for p in pp:
if p.parent():
print p.parent().kind(), p.parent_key()

Model.kind() の意味がようやくわかった。
http://code.google.com/appengine/docs/datastore/modelclass.html#Model_kind

2008年6月29日日曜日

don't add support for other languages の気持

はじめは PHP でなくて Python か、と思っていましたが、以下の表題に同意するといいいますか、
なとなく気持ちがわかるような気がしています。

Please don't add support for other languages.
http://groups.google.com/group/google-appengine/t/93d7fff1f3cfec95?hl=en

Google App Engine Helper for Django を使おうとしてみた

1. Google App Engine Helper for Django を使う
http://mars.shehas.net/~tmatsuo/misc/appengine_helper_for_django-ja.html
を参考に
http://code.google.com/p/google-app-engine-django/
から appengine_helper_for_django-r30.zip を download

2. これをテスト用の helloworld フォルダ以下に展開しようかとも、思ったが、そういうことはしてはいけない。( app.yaml ファイルなどもある)

C:\google\appengine_helper_for_django に展開


3. UNIX の場合 ln -s /path/to/google_appengine .google_appengine

appengine_helper_for_django は GAE の SDK にアクセスする。
Windows でも ln -s  できたはずなのでやり方を確認したが fsutil はファイル単位だけのサポートでフォルダには対応していないので、ろいろツールは作成されているようですが、
どうも Windows のシンボリックリンクのようなものは信用できない。
結局、物理的に C:\Program Files\Google\google_appengine を copy。

4. 起動 ( 拡張子 .py が c:python25\python.exe に関連づけされている)

C:\google\appengine_helper_for_django>manage.py runserver
WARNING:root:Loading the SDK from the 'google_appengine' subdirectory is now deprecated!
WARNING:root:Please move the SDK to a subdirectory named '.google_appengine' instead.
WARNING:root:See README for further details.
WARNING:root:Could not read datastore data from c:\docume~1\xxx\locals~1\temp\django_google-app-engine-django.datastore
WARNING:root:Could not read datastore data from c:\docume~1\xxx\locals~1\temp\django_google-app-engine-django.datastore.history
WARNING:root:Could not initialize images API; you are likely missing the Python "PIL" module. ImportError: No module named PIL
INFO:root:Server: appengine.google.com
INFO:root:Checking for updates to the SDK.
INFO:root:The SDK is up to date.
WARNING:root:Could not read datastore data from c:\docume~1\xxx\locals~1\temp\django_google-app-engine-django.datastore
WARNING:root:Could not read datastore data from c:\docume~1\xxx\locals~1\temp\django_google-app-engine-django.datastore.history
WARNING:root:Could not initialize images API; you are likely missing the Python "PIL" module. ImportError: No module named PIL
INFO:root:Running application google-app-engine-django on port 8080: http://localhost:8080


5. 起動されたようなのでアクセスしてみる http://localhost:8080/
Welcome to Django
It worked!
Congratulations on your first Django-powered page.

Of course, you haven't actually done any work yet. Here's what to do next:

* If you plan to use a database, edit the DATABASE_* settings in settings/settings.py.
* Start your first app by running python settings/manage.py startapp [appname].

You're seeing this message because you have DEBUG = True in your Django settings file and you haven't configured any URLs. Get to work!





6. manage.py startapp polls を実行、コンソールにあいかわらず警告がでるが、以下が作成される。
C:\google\appengine_helper_for_django\polls
polls/
__init__.py
models.py
views.py

7. モデルの作成
polls/models.py

from django.db import models

# Create your models here.
from appengine_django.models import BaseModel
from google.appengine.ext import db

class Poll(BaseModel):
question = db.StringProperty()
pub_date = db.DateTimeProperty('date published')

class Choice(BaseModel):
poll = db.ReferenceProperty(Poll)
choice = db.StringProperty()
votes = db.IntegerProperty()


8. settings.py の INSTALLED_APPS にpolls を追加


INSTALLED_APPS = (
'appengine_django',
'django.contrib.auth',
'polls',
# 'django.contrib.contenttypes',
# 'django.contrib.sessions',
# 'django.contrib.sites',
)


9. manage.py shell

>>> class Poll(BaseModel):
... question = db.StringProperty()
... pub_date = db.DateTimeProperty('date published')
...
Traceback (most recent call last):
File "", line 1, in
File "C:\google\appengine_helper_for_django\appengine_django\models.py", line 109,in __new__
new_class._meta = ModelOptions(new_class)
File "C:\google\appengine_helper_for_django\appengine_django\models.py", line 49, in __init__
model_module = sys.modules[cls.__module__]
KeyError: '__console__'
>>>


Django をみてみないと。 テンプレート機能だけしか使っていない。
以前、 An example of using Django on top of App Engine はみたのだけれども。

2008年6月27日金曜日

Key.from_path( kind, id ), key_name is not unique in Kind

http://code.google.com/appengine/docs/datastore/keyclass.html#Key_from_path

ある kind のデータの id (or key_name)がわかっているとき
 greeting = db.get(db.Key.from_path('Greeting', int(id)))
のような使い方ができるが、さらに、その親の条件をつけることができる。

k = Key.from_path('User', 'Boris', 'Address', 9876)
User:親の kind 名  Boris はこの kind の key_name(=id)


親が異なれば、key_name は同じものをいくつも登録することができる。
つまり、 kind のなかで key_name は必ずしも Unique ではない。

ちなみに key_name は小文字

NewSection = Section(parent=band, Title="Net", URL="News21", Type="News",key_name="k2")
NewSection.put()


"where ANCESTOR IS :1", oya_key

http://googleappengine.blogspot.com/2008/04/posted-by-ken-ashcraft-software.html

  • Avoid large entity groups. Any two entities that share a common ancestor belong to the same entity groups. All writes to an entity group are sequential, so large entity groups can bog down popular apps quickly if there are a lot of writes to that group. Instead, use small, localized groups in your design.

#490 のようなbugはあるようだけれども

NewBand = Band(Name="Test", URL="Test", Description="A test description")
NewBand.put()

NewSection = Section(parent=NewBand, Title="News", URL="News", Type="News")
NewSection.put()


子のput ()の際に parent を設定しておけば、ancector is に親キーを指定して、検索する
ことができる。

oya_key = db.GqlQuery("select * from Band")[0].key()
ko = db.GqlQuery("select * from Section where ANCESTOR IS :1", oya_key )



http://groups.google.com/group/google-appengine/browse_thread/thread/ad5175429f2f61f2
App works locally, but fails when uploaded
x = Section.all().ancestor(self).filter("URL = ", SectionURL).get

Property Names

name Property は alias ということ。

from google.appengine.ext import db

class MyModel(db.Model):
obj_key = db.StringProperty(name="key11")
content = db.StringProperty()

r = db.GqlQuery("select * from MyModel")
for rr in r:
print rr.content , rr.obj_key, key11
---
test None test



Transactions

Docs > Datastore API > Transactions

from google.appengine.ext import db

class Accumulator(db.Model):
 counter = db.IntegerProperty()
 a = Accumulator()
 a.counter = 0
 a.put()

def increment_counter(key, amount):
 obj = db.get(key)
 obj.counter += amount
 obj.put()

q = db.GqlQuery("SELECT * FROM Accumulator")
acc = q.get()
db.run_in_transaction(increment_counter,acc.key(), 5)
r = db.GqlQuery("select * from Accumulator" )

for rr in r:
 print rr.counter
----
5

MacOS Sequoia で Apache+PHP の再設定

 新しいXcodeが使いたかったので MacOS15(Sequoia) にアップグレードしたところ、やはりApacheでPHPが動かなくなっていた。 結論としては brew, openssl, php, httpd を全て再度インストールしたところ動くようになった。 以下、作業ロ...