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

 
Entities and Models
一个 entity 有一个 key 和属性集。应用程序利用 API 来定义数据模型,并且建立模型的实例来存储 entity 模型为这些 API 创建的 entity 提供一个通用的结构,并能定义规则来效验属性值。
Datastore Entities
大家都知道在 GAE 存储的一个数据对象称为 entity 。一个 entity 有多个属性,表示几种支持的数据类型中的一种的值。
每个 entity 都有一个 key 唯一标识这个 entity 。最简单的 key 有一个表类型和一个唯一的数字 id ,是 GAE 给它提供的。 这个 ID 值也可以是应用程序提供的一个字符串。 更多的信息参考 Keys and Entity Groups.
 
一个应用程序可以通过 key 从数据存储中 取出一个 entity ,或者通过匹配 entity 的属性来查询也可以。一个查询还可以匹配 key 的“祖先”。参阅 Keys and Entity Groups ,一个查询可以返回 0 或者多条记录的 entity 。并可以预先排序。也可以限制返回的结果行数以节约内存。
 
不象传统的数据库, GAE 不需要所有某种 dentity 都有相同的属性。应用程序能够通过 API 来规约他们的数据模型。
The Model Interface
利用模型,应用程序描述了数据的不同类型。一个模型是一个 python 类,继承自 Model 类。这个模型类定义了一个新的 entity 类型和以及这个类型所期望具备的属性。模型类利用 python 类的 attributes 来定义模型属性。每个类 attribute Property 子类的实例。通常是一些已经定义好的属性类。一个属性实例包含了属性的配置,例如效验是否必须录入,或者当没有提供值的时候给它一个缺省值。
from google . appengine . ext import db

class Pet ( 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 )
在编程接口里面,一个模型类对应的实例表现为一个表类型的 entity 。应用程序通过构造方法产生一个 entity 。通过实例的 attributes 来对属性进行存储。构造函数通过参数得到属性的初始值。
from google . appengine . api import users

pet
= Pet ( name = "Fluffy" ,
          type
= "cat" ,
          owner
= users . get_current_user ())
pet
. weight_in_pounds = 24
注意:模型类的 attributes 是配置模型的属性的,他们的值是 Property 类的实例。模型实例的 attribute 是实际的属性值,是 python 类能够接受的值。
模型类利用 Property 实例来校验给模型实例的属性赋的值。当模型对象一开始建立校验就起作用了,在修改的时候也会进行校验。这保证了属性永远不会非法。由于实例构建的时候就开始校验,标志为必须录入的属性必须在构造方法里面提供值。在这个例子里面, name type owner 都是 required 的,因此调用构建函数的时候就需要提供。而 weight in pounds 就不需要,所以一开始它们是没有赋值,可以在之后的程序当中赋值。
模型实例创建之后并没有在 datastore 里面存储的,必须在调用 put 方法之后才真正写入数据库。
 
注意:模型属性配置以及所有的 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( 不太理解 )
Expando Models
一个模型定义利用模型类建立固定数量的属性。所有的实例都必须具备这些属性。这是通常的做法,但是 GAE 其实并不需要所有的 entity 具有所有同样的属性。
 
有时候,一个 entity 和其它同类的 entity 具有不同的属性,是很有用的。这种 entity API 里面表示为 expando 模型。一个 expando 模型类是 Expando 的子类。任何赋给 expando 实例的 attribute 的值变成 entity 的同名属性,这些属性叫做动态属性,而那些用 Property 类实例定义了的属性是固定属性。
一个 expando 模型可以同时具备固定属性和动态属性。固定属性是类模型用属性配置来定义的,而动态属性是应用程序在赋值给的时候才建立它们。
class Person ( 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
由于动态属性没有相应的模型属性定义,动态属性不会被校验。任何动态属性可以具备基本类型的值,包括 None 。同类的 2 entity 同一个动态属性可以有不同类型的值,也可以一个设置了属性而另外一个不设置。
                                                                                                
和固定属性不同,动态属性不一定存在。一个具有 None 值的动态属性不同于不存在的动态属性。如果 expando 模型实例没有任何动态属性,对应的数据 entity 就没有这些属性,你可以删除通过删除 attribute 来删除一个动态属性。
del p . chess_elo_rating
一个在过滤里面用了动态属性的查询将只返回数据类型和查询语句一致的那些 entity 。同样的,查询将值返回设置了指定属性的 entities
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
Expando 类是 Model 类的子类,并继承所有它的方法。
Properties and Types
Entity 属性支持固定的一些类型,包括 unicode ,整数,浮点,日期, key byte ,二进制,和各种 GData 类型。每种类型都对应 Property 的子类,在 google.appengine.ext.db 里面定义。
 
这里: Types and Property Classes 描述了所有支持的属性类,有几种特殊的类型下面介绍一下。
Strings, Long Strings and Blobs
Datastore 支持 2 中类型的文本:短字符串, 500 字节以下,长字符串, 500 以上。短字符串可以被索引并能够在查询的过滤子句里面用,也可以排序,长的就不行。
 
短字符串可以是 unicode 或者 str 值。如果是一个 str ,缺省是 ’ascii’ 编码。为 str 值指定一个不同的编码,可以用 unicode() 类型构造函数,把它转换为 unicode 值,参数是 str 和编码的名字。短字符串可以用 StringProperty 类来建模。
class MyModel ( 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" )
一个长字符串对应 db.Text 实例。它的构造器可以用 unicode 或者 str 值,和一个类型的可选参数。长字符串可用 TextProperty 类来建模
class MyModel ( 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" )
Datastore 还支持非文本的类型, Blob ,和长字符串一样, blob 不会被索引,也不可过滤查询、排序。 Blob 实例表现为字符字节的集合,创建时用 str 值来作为参数。用 BlogProperty 建模
class MyModel ( db . Model ):
  blob
= db . BlobProperty ()

obj
= MyModel ()

obj
. blob = db . Blob ( open ( "image.png" ). read ())
Lists
一个属性可以有多个值,在 datastore API 表现为 Python list List 包含任意被 datastore 支持的类型。
 
ListProperty 构建 list 模型,并强制 list 里面所有的值为指定的类型。为了方便,库提供了 StringListProperty ,等同于 ListProperty(basestring) .
 
class MyModel ( 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.
一个查询过滤 List 属性检测 list 的成员。如果至少有一个成员符合条件就通过这个条件过滤。
# 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" )
查询过滤只作用于成员。没办法测试 2 list 是否一致。
 
内部处理上, datastore 用多个值来表示 list 属性。如果一个 list 属性值是空列表,那么这个属性就没有表现在 datastore 。编程接口对待于静态的 ListProperty 属性和动态属性,是不一样的处理的。
  • 一个静态的 ListProperty 能够把一个空的 list 赋值给它。这个值在 datastore 不存在,但模型实例表现为好像这个值是一个空的 list 。静态的 ListProperty 不能够是 None 值。
  • 一个 List 动态属性的值不能够是一个空的 list 。然而它可以是 None ,并可以删除。
  由于列表属性这种存储方式,对列表属性的排序不常见。
  • 如果 entities 对列表属性进行正序排序,用来排序的值是列表的最小元素。
  • 如果 entities 倒序排序,用列表最大的值来排序。
  •   其它列表元素既不影响排序也,列表长度也不影响排序。
  • In the case of a tie, the key of the entity is used as the tie-breaker. ( 不太理解 ) 。这个排序会导致 [1..9] 不管是倒序还是正序都是在 [4, 5, 6, 7] 的前面,这种没意思的结果。
References
一个属性值可以包含扩其它 entity key 。这个值是一个 Key 类型的实例。
RefrenceProperty 类对 key 值建模,并迫使所有的值对应某个类型的 entity 。为了方便使用,提供了 SelfReferenceProperty 类型指向自己。
class FirstModel ( db . Model ):
  prop
= db . IntegerProperty ()

class SecondModel ( 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
一个 ReferenceProperty 属性值象一个模型实例 entity 一样的使用。如果引用的 entity 在内存不存在,访问它的时候自动从存储 里面取出相应记录。
obj2 . reference . prop = 999
obj2
. reference . put ()

results
= db . GqlQuery ( "SELECT * FROM FirstModel" )
another_obj
= results . fetch ( 1 )[ 0 ]
v
= another_obj . reference . prop
当一个 entity 的关联属性值执行了删除,这个关联属性不会被改变。一个关联属性值不能是一个不再有效的 key 。如果应用程序认为可以存在无效的关联,可以用 db.get() 来取出 entity ,并在使用它之前检测它的属性值。
obj1 = db . get ( obj2 . reference )

if not obj1 :
 
# Referenced entity was deleted.
ReferenceProperty 有另外的方便特征:往回关联。如果一个模型 ReferenceProperty 了另外一个模型,每个被关联的 entity 得到一个属性,它返回第一个指向它的模型一个查询结果 entities
# To fetch and iterate over every SecondModel entity that refers to the
# FirstModel instance obj1:
for obj in obj1 . firstmodel_set :
 
# ...
往回关联属性缺省是 modelname_set(_set  前面的名字是模型类的小写名字 ) ,也可以在 ReferenceProperty 的构造函数的用 collection_name 参数来改变。
 
只有在使用 ReferenceProperty 模型属性类的时候,可以自动关联和废弃关联 , 类型检查和往回关联。用 Expando 动态属性或者 ListProperty 来储存 key 值的就没有这些特征了。
Property Names
Datastore 用前后的 2 个连续下划线保留所有的属性名称,应用程序必须避免这样的命名来定义属性。
 
 
因为缺省情况下 Python API 用模型实例的 attributes 来作为属性名称,所以那些已经被实例方法用过的 attributes ,就不能再作为属性名字了。同样的,模型构造方法里面 keyword 参数里面的名字也都不能用作属性的名字。
 
 
但其实 Datastore 本身是允许这些名字的。如果一个应用程序需要一个 entity
python API 保留的关键字作为属性名称,程序可以在构造函数用 name 参数来指定固定属性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值