Python 将属性内置于GAE数据存储';s模型
我想创建GAE模型属性的属性。原因是case喜欢在存储值之前将其转换为大写。对于普通Python类,我将执行以下操作:Python 将属性内置于GAE数据存储';s模型,python,google-app-engine,google-cloud-datastore,Python,Google App Engine,Google Cloud Datastore,我想创建GAE模型属性的属性。原因是case喜欢在存储值之前将其转换为大写。对于普通Python类,我将执行以下操作: Foo(db.Model): def get_attr(self): return self.something def set_attr(self, value): self.something = value.upper() if value != None else None attr = property(get_at
Foo(db.Model):
def get_attr(self):
return self.something
def set_attr(self, value):
self.something = value.upper() if value != None else None
attr = property(get_attr, set_attr)
然而,GAE数据存储有自己的属性类概念,我研究了属性类,似乎可以覆盖get\u value\u以实现我的目标。然而,我不知道什么是model\u instance
,以及如何从中提取相应的字段
重写GAE属性类是提供类似getter/setter的功能的正确方法吗?如果是,怎么做
添加:
我想到的为_datastore
重写get_value_的一个潜在问题是,在将对象放入数据存储之前,它可能不会被调用。因此,在存储对象之前获取属性将产生不正确的值。如果您希望在一个或多个模型中有多个具有类似行为的“字段”,则对GAE的类进行子类化尤其有用。别担心,get_value\u for_datastore
和make_value\u from_datastore
将分别在任何存储和获取上被调用——因此,如果您需要做任何花哨的事情(包括但不限于大写字符串,实际上并不那么花哨;-),在子类中重写这些方法很好
Edit:让我们看看一些示例代码(扣除导入和main
):
这将显示字符串在数据存储中已大写——但是如果将get
调用更改为简单的mm=my
,您将看到内存中的实例没有受到影响
但是,db.Property
实例本身就是一个描述符——将其包装到内置的属性
(一个完全不同的描述符)中不会很好地用于数据存储(例如,您不能基于字段名编写GQL查询,这些字段名实际上不是db.Property
的实例,而是Property
的实例——这些字段在数据存储中不是)
因此,如果您想同时使用数据存储和Model
的实例,而这些实例实际上从未访问过数据存储并返回,那么您必须为逻辑上“相同”的内容选择两个名称字段——一个是要在内存模型实例上使用的属性的名称,一个可以是内置的属性
;另一个是在数据存储中结束的属性的名称,该名称需要是db.property
子类的实例,并且在查询中需要使用第二个名称。当然,第一个名字背后的方法需要读写第二个名字,但你不能只是“隐藏”第二个名字,因为这是数据存储中的名字,所以这是对查询有意义的名字!如果你想要多个“字段”,子类化GAE的类尤其有用在一个或多个模型中,使用类似的行为。不要担心,get\u value\u for_datastore
和make\u value\u from_datastore
将分别在任何存储和获取上被调用——因此,如果您需要做任何花哨的事情(包括但不限于大写字符串,实际上并不那么花哨;-),在子类中重写这些方法就可以了
Edit:让我们看看一些示例代码(扣除导入和main
):
这将显示字符串在数据存储中已大写——但是如果将get
调用更改为简单的mm=my
,您将看到内存中的实例没有受到影响
但是,db.Property
实例本身就是一个描述符——将其包装到内置的属性
(一个完全不同的描述符)中不会很好地用于数据存储(例如,您不能基于字段名编写GQL查询,这些字段名实际上不是db.Property
的实例,而是Property
的实例——这些字段在数据存储中不是)
因此,如果您想同时使用数据存储和
Model
的实例,而这些实例实际上从未访问过数据存储并返回,那么您必须为逻辑上“相同”的内容选择两个名称字段——一个是要在内存模型实例上使用的属性的名称,一个可以是内置的属性
;另一个是在数据存储中结束的属性的名称,该名称需要是db.property
子类的实例,并且在查询中需要使用第二个名称。当然,第一个名字背后的方法需要读写第二个名字,但你不能只是“隐藏”后者是因为这是数据存储中的名称,因此这是对查询有意义的名称!您想要的是一个。在那篇文章中概述了编写一个的过程-这与Alex所描述的类似,但是通过覆盖get而不是get\u value\u for\u数据存储,您避免了ne的问题正在写入数据存储以更新它。我的库中包含了它和其他有用的属性。您想要的是一个。在那篇文章中概述了写入一个的过程-它与Alex描述的类似,但是通过覆盖get而不是get\u value\u for\u datastore,您可以避免需要写入数据的问题存储以更新它。我的库中包含了它和其他有用的属性。我尝试使用覆盖的get\u value\u for\u数据存储扩展StringProperty,但我似乎没有做任何事情。为什么?忽略我的上述注释,这是我的错误。覆盖StringProperty确实有效。但是,我担心,只有在对象被放置到数据存储。我希望有一种方法
class MyStringProperty(db.StringProperty):
def get_value_for_datastore(self, model_instance):
vv = db.StringProperty.get_value_for_datastore(self, model_instance)
return vv.upper()
class MyModel(db.Model):
foo = MyStringProperty()
class MainHandler(webapp.RequestHandler):
def get(self):
my = MyModel(foo='Hello World')
k = my.put()
mm = MyModel.get(k)
s = mm.foo
self.response.out.write('The secret word is: %r' % s)