本文共 14345 字,大约阅读时间需要 47 分钟。
from google.appengine.ext import dbfrom google.appengine.api import usersclassPet(db.Model): name = db.StringProperty(required=True) type = db.StringProperty(required=True, choices=set(["cat","dog","bird"])) birthdate = db.DateProperty() weight_in_pounds = db.IntegerProperty() spayed_or_neutered = db.BooleanProperty() owner = db.UserProperty()pet =Pet(name="Fluffy", type="cat", owner=users.get_current_user())pet.weight_in_pounds =24pet.put()
if users.get_current_user(): user_pets = db.GqlQuery("SELECT * FROM Pet WHERE pet.owner = :1", users.get_current_user()) for pet in user_pets: pet.spayed_or_neutered =True db.put(user_pets)
·
·
·
·
Model 或者Expando类的实例表示entity。应用程序通过对应模型类的构造方法来创建新的实例 entity。
pet=Pet(name="Fluffy", type="cat", owner=users.get_current_user())
直到第一次调用 put()方法之后,新的数据entity才写入数据库datastore。可以直接调用对象的put方法,也可以调用 db.put()
pet.put() db.put(pet)
如果entity已经在数据库存在了,那么put()方法会去更新它。
查询返回多个模型实例。这些实例可以修改并更新回datastore.
if users.get_current_user(): user_pets = db.GqlQuery("SELECT * FROM Pet WHERE pet.owner = :1", users.get_current_user()) for pet inuser_pets: pet.spayed_or_neutered=True db.put(user_pets)
Datastore能够执行查询某个类型的entity。一个查询可以用条件子句来过滤entity的属性值,并能够返回经过排序的结果集。一个查询也可以通过祖先来限制查询结果的范围。
完整对查询语句的描述信息,包括它不能够做什么,请参阅.
DatastoreAPI 通过 2 中界面来执行查询: Query ,用查询对象的一些方法。还有 GqlQuery ,是一种类似 SQL 的语言。The Query Interface
Model 或者Expando的all() 方法返回查询对象,对应这种表类所有的entity。应用程序通过Filter()、Order()、ancesitor()来准备查询。
classStory(db.Model): title = db.StringProperty() date = db.DateTimeProperty() query =Story.all() query.filter('title=','Foo') query.order('-date') query.ancestor(key) # These methods can bechained together on one line. query.filter('title=','Foo').order('-date').ancestor(key)
The GqlQuery Interface
GqlQuery类构造函数的参数包括查询语句和可选的参数。语句包括数据的种类,条件过滤,排序还有祖先条件。还可以包括对结果集的限制以及偏移。
# Parameters can be bound with positional arguments. query = db.GqlQuery("SELECT * FROM Story WHERE title = :1 " "AND ANCESTOR IS :2 " "ORDER BY date DESC", 'Foo',key) # Or, parameters can be boundwith keyword arguments. query = db.GqlQuery("SELECT * FROM Story WHERE title = :title " "AND ANCESTOR IS :parent " "ORDER BY date DESC", title='Foo', parent=key) # String, number and Booleanvalues can be literal values in the string. query = db.GqlQuery("SELECT * FROM Story WHERE title = 'Foo' " "AND ANCESTOR IS :parent " "ORDER BY date DESC", parent=key)
Model类的Gql()方法也是从查询语句来准备一个GqlQuery对象。相对来说它隐藏了select * from model的语句,因为已经隐含包含了。
query=Story.gql("WHERE title= :title " "AND ANCESTOR IS :parent " "ORDER BY date DESC", title='Foo', parent=key)
可以用bind()方法来再次绑定参数。应用程序可以通过重新绑定参数的方法来重新利用GqlQuery对象。
一直等到应用程序操作结果集的时候,Query和GqlQuery 对象才真正执行查询。当程序操作返回结果的时候,查询就会被执行了。结果将作为模型类的实例存储在内存里面。每个查询类都提供2个途径来执行查询和操作结果,fetch()方法,和迭代器。
Fetch()方法返回最大的数量(limit),一个可选的参数用于跳过(偏移值)。这个方法会执行查询,返回记录,直到没有为止。一旦所有的结果被放到内存里面,结果集作为list列表的形式返回(如果指定了偏移它会忽略响应的记录)。如果调用fetch()都会执行一个完全的查询。
注意:偏移参数不会影响返回的结果行数。所有超过它限制的记录都被返回到内存中。偏移参数只影响返回哪些记录
results= query.fetch(10) for result in results: print"Title: "+ result.title
Fetch()方法里面的行数限制和偏移会覆盖GQL里面的。
如果是在迭代器里面用,查询的执行将不会有限制和偏移,结果返回到内存中。所有结果在每次的迭代中被返回,迭代变量对应产生模型的实例。
for resultin query: print"Title: "+ result.title
注意:Query有一个系统的最大限制:1000行。如果没有指定限制,或者指定的限制大于最大限制,那么将采用最大限制。
entity.put() key = entity.key() # ... entity = db.get(key)
Key值的常见用处是在其它的entity中用一个属性来存储。类把自动引用和废弃引用key:一个模型实例可以直接赋值给一个ReferenceProperty。并且它的key可以代替值来引用。
classPet(db.Model): name =StringProperty() owner =ReferenceProperty(PetOwner) classPetOwner(db.Model): name =StringProperty() owner =PetOwner(name="Albert") pet =Pet(name="Fluffy",owner=owner) # This is equivalent: pet =Pet(name="Fluffy",owner=owner.key())
类似的,通过ReferenceProperty属性对它的访问和访问它自身的实例一样,也是在fetch()的时候自动进行的,如果没有访问就不会fetch()
pets=GqlQuery("SELECT * FROM Pet WHERE name =:1","Fluffy") pet = pets.get() owner_name = pet.owner.name
如果不是用ReferenceProperty存储key值,例如 Expando动态属性,或者 ListProperty 元素,就没有自动废弃关联的行为。(好像不太对。。。)
Db.get()函数通过key或者key的列表可以从datastore返回entity。
Key可以被编码为字符串分发给应用程序的外部。然后把字符编码传递给Key类的构造函数可以重新得到key对象。
obj=MyModel(name="Foo") self.response.write('<ahref="/view?key=%s">%s</a>'%(str(obj.key()), obj.name())) # ... key_name = self.request.get('key') obj = db.get(db.Key(key_name))
注意:对key的字符串编码是虽然是晦涩难懂的,但没有加密,如果你的程序需要key是不能够猜测的,你要在在把key传送给用户之前加密它。
应用程序能够根据模型实例或者key值来删除一个entity。实例方法是:delete()。Db.delete()则通过key值或者key值列表来删除。
q= db.GqlQuery("SELECT * FROM Message WHERE create_date < :1", earliest_date) results = q.fetch(10) for result in results: result.delete() # db.delete() requires thatall entities in one call be of the same # entity group, because allof the deletes happen in one transaction. q = db.GqlQuery("SELECT* FROM Message WHERE create_date < :1"+ "AND ANCESTOR IS :2", earliest_date, parent) results = q.fetch(10) db.delete(results)
删除一个entity不会改变引用它的key值。如果需要进行废除关联一个已经删除的entity,应用程序应调用db.get(),在访问属性的时候测试一下返回值。
删除一个其它entity 的祖先 entity不会影响其它的entity。因为程序并不需要根据祖先entity 来构建后代entity 的key,所以后代entity 仍然是可以访问的。
转载地址:http://kwzub.baihongyu.com/