您的位置:首页 > 移动开发

GAE(Google App Engine Datastore API)翻译(2)

2008-05-27 10:54 736 查看
[align=left]Entities and Models[/align]
[align=left]一个entity 有一个key 和属性集。应用程序利用API 来定义数据模型,并且建立模型的实例来存储entity。模型为这些API创建的entity提供一个通用的结构,并能定义规则来效验属性值。[/align]

[align=left][/align]

[align=left]Datastore Entities[/align]

[align=left]大家都知道在GAE 存储的一个数据对象称为 entity。一个entity 有多个属性,表示几种支持的数据类型中的一种的值。[/align]
[align=left]每个entity 都有一个key 唯一标识这个entity。最简单的key 有一个表类型和一个唯一的数字id,是GAE给它提供的。这个ID值也可以是应用程序提供的一个字符串。更多的信息参考Keys and Entity Groups.[/align]
[align=left] [/align]
[align=left]一个应用程序可以通过key从数据存储中取出一个entity,或者通过匹配entity 的属性来查询也可以。一个查询还可以匹配key 的“祖先”。参阅 Keys and Entity Groups,一个查询可以返回0或者多条记录的entity。并可以预先排序。也可以限制返回的结果行数以节约内存。[/align]
[align=left] [/align]
[align=left]不象传统的数据库,GAE不需要所有某种dentity都有相同的属性。应用程序能够通过API来规约他们的数据模型。[/align]

[align=left]The Model Interface[/align]

[align=left]利用模型,应用程序描述了数据的不同类型。一个模型是一个python 类,继承自Model类。这个模型类定义了一个新的entity类型和以及这个类型所期望具备的属性。模型类利用python类的attributes来定义模型属性。每个类attribute是Property子类的实例。通常是一些已经定义好的属性类。一个属性实例包含了属性的配置,例如效验是否必须录入,或者当没有提供值的时候给它一个缺省值。[/align]

[align=left]from google.appengine.ext import db

classPet(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(required=True)[/align]

[align=left]在编程接口里面,一个模型类对应的实例表现为一个表类型的entity。应用程序通过构造方法产生一个entity。通过实例的attributes来对属性进行存储。构造函数通过参数得到属性的初始值。[/align]

[align=left]from google.appengine.api import users

pet =Pet(name="Fluffy",
type="cat",
owner=users.get_current_user())
pet.weight_in_pounds =24[/align]

[align=left]注意:模型类的attributes是配置模型的属性的,他们的值是Property 类的实例。模型实例的attribute是实际的属性值,是python 类能够接受的值。[/align]

[align=left]模型类利用Property 实例来校验给模型实例的属性赋的值。当模型对象一开始建立校验就起作用了,在修改的时候也会进行校验。这保证了属性永远不会非法。由于实例构建的时候就开始校验,标志为必须录入的属性必须在构造方法里面提供值。在这个例子里面,name,type 和owner 都是required 的,因此调用构建函数的时候就需要提供。而weight in pounds 就不需要,所以一开始它们是没有赋值,可以在之后的程序当中赋值。[/align]
[align=left]模型实例创建之后并没有在datastore 里面存储的,必须在调用put方法之后才真正写入数据库。[/align]
[align=left] [/align]

[align=left]注意:模型属性配置以及所有的python 类attribute,在模块或者脚本第一次导入的时候初始化。因为GAE 在request里面缓存了导入的模块,模块配置可能在一个用户请求之后,重新被其它用户请求所利用。Do not initialize model property configuration, such as default values, with data specific to the request or the current user. See App Caching for more information(不太理解)[/align]

[align=left]Expando Models[/align]

[align=left]一个模型定义利用模型类建立固定数量的属性。所有的实例都必须具备这些属性。这是通常的做法,但是GAE 其实并不需要所有的entity具有所有同样的属性。[/align]
[align=left] [/align]
[align=left]有时候,一个entity和其它同类的entity具有不同的属性,是很有用的。这种entity 在API 里面表示为 expando 模型。一个expando 模型类是Expando 的子类。任何赋给expando实例的attribute的值变成entity 的同名属性,这些属性叫做动态属性,而那些用Property类实例定义了的属性是固定属性。[/align]
[align=left]一个expando模型可以同时具备固定属性和动态属性。固定属性是类模型用属性配置来定义的,而动态属性是应用程序在赋值给的时候才建立它们。[/align]

[align=left]classPerson(db.Expando):
first_name = db.StringProperty()
last_name = db.StringProperty()
hobbies = db.StringListProperty()

p =Person(first_name="Albert", last_name="Johnson")
p.hobbies =["chess","travel"]

p.chess_elo_rating =1350

p.travel_countries_visited =["Spain","Italy","USA","Brazil"]
p.travel_trip_count =13[/align]

[align=left]由于动态属性没有相应的模型属性定义,动态属性不会被校验。任何动态属性可以具备基本类型的值,包括 None。同类的2个entity同一个动态属性可以有不同类型的值,也可以一个设置了属性而另外一个不设置。[/align]
[align=left] [/align]
[align=left]和固定属性不同,动态属性不一定存在。一个具有None值的动态属性不同于不存在的动态属性。如果expando 模型实例没有任何动态属性,对应的数据entity就没有这些属性,你可以删除通过删除 attribute 来删除一个动态属性。[/align]

[align=left]del p.chess_elo_rating[/align]

[align=left]一个在过滤里面用了动态属性的查询将只返回数据类型和查询语句一致的那些entity。同样的,查询将值返回设置了指定属性的entities。[/align]

[align=left]p1 =Person()
p1.favorite =42
p1.put()

p2 =Person()
p2.favorite ="blue"
p2.put()

p3 =Person()
p3.put()

people = db.GqlQuery("SELECT * FROM Person WHERE favorite < :1",50)
# people has p1, but not p2 or p3

people = db.GqlQuery("SELECT * FROM Person WHERE favorite > :1",50)
# people has no results[/align]

[align=left]Expando 类是Model 类的子类,并继承所有它的方法。[/align]

[align=left]Properties and Types[/align]

[align=left]Entity属性支持固定的一些类型,包括unicode,整数,浮点,日期,key,byte,二进制,和各种GData 类型。每种类型都对应Property的子类,在google.appengine.ext.db 里面定义。[/align]
[align=left] [/align]
[align=left]这里:Types and Property Classes 描述了所有支持的属性类,有几种特殊的类型下面介绍一下。[/align]
[align=left]Strings, Long Strings and Blobs[/align]
[align=left]Datastore 支持2中类型的文本:短字符串,500字节以下,长字符串,500以上。短字符串可以被索引并能够在查询的过滤子句里面用,也可以排序,长的就不行。[/align]
[align=left] [/align]
[align=left]短字符串可以是unicode或者str 值。如果是一个str,缺省是’ascii’编码。为str值指定一个不同的编码,可以用unicode()类型构造函数,把它转换为unicode 值,参数是str 和编码的名字。短字符串可以用 StringProperty 类来建模。[/align]

[align=left]classMyModel(db.Model):
string= db.StringProperty()

obj =MyModel()

# Python Unicode literal syntax fully describes characters in a text string.
obj.string= u"kittens"

# unicode() converts a byte string to a Unicode value using the named codec.
obj.string= unicode("kittens","latin-1")

# A byte string is assumed to be text encoded as ASCII (the 'ascii' codec).
obj.string="kittens"

# Short string properties can be used in query filters.
results = db.GqlQuery("SELECT * FROM MyModel WHERE string = :1", u"kittens")[/align]

[align=left]一个长字符串对应 db.Text 实例。它的构造器可以用unicode 或者str 值,和一个类型的可选参数。长字符串可用TextProperty类来建模[/align]

[align=left]classMyModel(db.Model):
text = db.TextProperty()

obj =MyModel()

# Text() can take a Unicode value.
obj.text = db.Text(u"lots of kittens")

# Text() can take a byte string and the name of an encoding.
obj.text = db.Text("lots of kittens","latin-1")

# If no encoding is specified, a byte string is assumed to be ASCII text.
obj.text = db.Text("lots of kittens")

# Text properties can store large values.
obj.text = db.Text(open("a_tale_of_two_cities.txt").read(),"utf-8")[/align]

[align=left]Datastore 还支持非文本的类型,Blob,和长字符串一样,blob 不会被索引,也不可过滤查询、排序。Blob实例表现为字符字节的集合,创建时用str值来作为参数。用 BlogProperty建模[/align]

[align=left]classMyModel(db.Model):
blob = db.BlobProperty()

obj =MyModel()

obj.blob = db.Blob(open("image.png").read())[/align]

[align=left]Lists[/align]
[align=left]一个属性可以有多个值,在datastore API 表现为Python 的list。List 包含任意被datastore 支持的类型。[/align]
[align=left] [/align]
[align=left]ListProperty 构建list模型,并强制list里面所有的值为指定的类型。为了方便,库提供了StringListProperty,等同于ListProperty(basestring).[/align]
[align=left] [/align]

[align=left]classMyModel(db.Model):
numbers = db.ListProperty(long)

obj =MyModel()
obj.numbers =[2,4,6,8,10]

obj.numbers =["hello"] # ERROR: MyModel.numbers must be a list of longs.[/align]

[align=left]一个查询过滤List属性检测list 的成员。如果至少有一个成员符合条件就通过这个条件过滤。[/align]

[align=left]# Get all entities where numbers contains a 6.
results = db.GqlQuery("SELECT * FROM MyModel WHERE numbers = 6")

# Get all entities where numbers contains at least one element less than 10.
results = db.GqlQuery("SELECT * FROM MyModel WHERE numbers < 10")[/align]

[align=left]查询过滤只作用于成员。没办法测试2个list是否一致。[/align]
[align=left] [/align]
[align=left]内部处理上,datastore 用多个值来表示list 属性。如果一个list 属性值是空列表,那么这个属性就没有表现在datastore。编程接口对待于静态的ListProperty属性和动态属性,是不一样的处理的。[/align]

[align=left]一个静态的ListProperty能够把一个空的list赋值给它。这个值在datastore不存在,但模型实例表现为好像这个值是一个空的list。静态的ListProperty 不能够是 None值。[/align]

[align=left]一个List动态属性的值不能够是一个空的list。然而它可以是None,并可以删除。[/align]

[align=left] 由于列表属性这种存储方式,对列表属性的排序不常见。[/align]

[align=left]如果entities对列表属性进行正序排序,用来排序的值是列表的最小元素。[/align]

[align=left]如果entities 倒序排序,用列表最大的值来排序。[/align]

[align=left] 其它列表元素既不影响排序也,列表长度也不影响排序。[/align]

[align=left]In the case of a tie, the key of the entity is used as the tie-breaker. (不太理解)。这个排序会导致[1..9]不管是倒序还是正序都是在[4, 5, 6, 7]的前面,这种没意思的结果。[/align]

[align=left]References[/align]
[align=left]一个属性值可以包含扩其它entity的key。这个值是一个Key 类型的实例。[/align]
[align=left]RefrenceProperty 类对key值建模,并迫使所有的值对应某个类型的entity。为了方便使用,提供了SelfReferenceProperty 类型指向自己。[/align]

[align=left]classFirstModel(db.Model):
prop = db.IntegerProperty()

classSecondModel(db.Model):
reference = db.ReferenceProperty(FirstModel)

obj1 =FirstModel()
obj1.prop =42
obj1.put()

obj2 =SecondModel()

# A reference value is the key of another entity.
obj2.reference = obj1.key()

# Assigning a model instance to a property uses the entity's key as the value.
obj2.reference = obj1[/align]

[align=left]一个ReferenceProperty属性值象一个模型实例entity 一样的使用。如果引用的entity在内存不存在,访问它的时候自动从存储里面取出相应记录。[/align]

[align=left]obj2.reference.prop =999
obj2.reference.put()

results = db.GqlQuery("SELECT * FROM FirstModel")
another_obj = results.fetch(1)[0]
v = another_obj.reference.prop[/align]

[align=left]当一个entity的关联属性值执行了删除,这个关联属性不会被改变。一个关联属性值不能是一个不再有效的key。如果应用程序认为可以存在无效的关联,可以用db.get()来取出entity,并在使用它之前检测它的属性值。[/align]

[align=left]obj1 = db.get(obj2.reference)

ifnot obj1:
# Referenced entity was deleted.[/align]

[align=left]ReferenceProperty有另外的方便特征:往回关联。如果一个模型ReferenceProperty了另外一个模型,每个被关联的entity 得到一个属性,它返回第一个指向它的模型一个查询结果entities。[/align]

[align=left]# To fetch and iterate over every SecondModel entity that refers to the
# FirstModel instance obj1:
for obj in obj1.firstmodel_set:
# ...[/align]

[align=left]往回关联属性缺省是 modelname_set(_set 前面的名字是模型类的小写名字),也可以在ReferenceProperty 的构造函数的用collection_name 参数来改变。[/align]
[align=left] [/align]
[align=left]只有在使用 ReferenceProperty模型属性类的时候,可以自动关联和废弃关联,类型检查和往回关联。用Expando 动态属性或者ListProperty 来储存key值的就没有这些特征了。[/align]

[align=left]Property Names[/align]

[align=left]Datastore 用前后的2个连续下划线保留所有的属性名称,应用程序必须避免这样的命名来定义属性。[/align]
[align=left] [/align]
[align=left] [/align]
[align=left]因为缺省情况下Python API 用模型实例的attributes来作为属性名称,所以那些已经被实例方法用过的attributes,就不能再作为属性名字了。同样的,模型构造方法里面keyword参数里面的名字也都不能用作属性的名字。[/align]
[align=left] [/align]
[align=left] [/align]
[align=left]但其实Datastore本身是允许这些名字的。如果一个应用程序需要一个entity[/align]
[align=left]用python API 保留的关键字作为属性名称,程序可以在构造函数用name 参数来指定固定属性。[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: