Creating, Gettingand Deleting Data
DatastoreAPI 把 entity 用模型类的实例来表示。模型类的方法可以创建,修改和删除 entity 。利用查询,或者直接通过 key ,可以从物理 datastore 服务器里面得到 entity 。· Creating and Updating an Entity
· Getting Entities Using a Query
· Getting an Entity Using a Key
· Deleting an Entity
Creating and Updating an Entity
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)
Getting EntitiesUsing a Query
Datastore能够执行查询某个类型的entity。一个查询可以用条件子句来过滤entity的属性值,并能够返回经过排序的结果集。一个查询也可以通过祖先来限制查询结果的范围。
完整对查询语句的描述信息,包括它不能够做什么,请参阅Queries and Indexes.
DatastoreAPI 通过 2 中界面来执行查询: Query ,用查询对象的一些方法。还有 GqlQuery ,是一种类似 SQL 的语言。The Query Interface
Model 或者Expando 的all() 方法返回查询对象,对应这种表类所有的entity。应用程序通过Filter()、Order()、ancesitor() 来准备查询。
class Story(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 对象。
Executing the Query and Accessing Results
一直等到应用程序操作结果集 的时候,Query 和GqlQuery 对象才真正执行查询。当程序操作返回结果的时候,查询就会被执行了。结果将作为模型类的实例存储在内存里面。每个查询类都提供2个途径来执行查询和操作结果,fetch()方法,和迭代器。
Fetch()方法返回最大的数量(limit),一个可选的参数用于跳过(偏移值)。这个方法会执行查询,返回记录,直到没有为止。一旦所有的结果被放到内存里面,结果集作为list列表的形式返回(如果指定了偏移它会忽略响应的记录)。如果调用fetch()都会执行一个完全的查询。
注意:偏移参数不会影响返回的结果行数。所有超过它限制的记录都被返回到内存中。偏移参数只影响返回哪些记录
results = query.fetch(10)
for result in results:
print "Title: " + result.title
Fetch()方法里面的行数限制和偏移会覆盖GQL 里面的。
如果是在迭代器里面用,查询的执行将不会有限制和偏移,结果返回到内存中。所有结果在每次的迭代中被返回,迭代变量对应产生模型的实例。
for result in query:
print "Title: " + result.title
注意:Query 有一个系统的最大限制:1000行。如果没有指定限制,或者指定的限制大于最大限制,那么将采用最大限制。
Getting anEntity Using a Key
entity.put()
key = entity.key()
# ...
entity = db.get(key)
Key值的常见用处是在其它的entity 中用一个属性来存储。ReferenceProperty类把自动引用和废弃引用key:一个模型实例可以直接赋值给一个ReferenceProperty。并且它的key 可以代替值来引用。
class Pet(db.Model):
name = StringProperty()
owner = ReferenceProperty(PetOwner)
class PetOwner(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传送给用户之前加密它。
Deleting an Entity
应用程序能够根据模型实例或者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 仍然是可以访问的。