Подклассы * Свойство класса GAE особенно полезно, если вам нужно более одного "поля" с похожим поведением в одной или нескольких моделях. Не волнуйтесь, get_value_for_datastore
и make_value_from_datastore
будут вызываться в любом магазине и при получении соответственно - поэтому, если вам нужно сделать что-нибудь необычное (включая, помимо прочего, верхний регистр строки, что на самом деле не все , что причудливо ;-), переопределение этих методов в вашем подклассе просто прекрасно.
Редактировать : давайте рассмотрим пример кода (за вычетом импорта и main
):
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)
Это показывает, что строка была в верхнем регистре в хранилище данных - но если вы измените вызов get
на простой mm = my
, вы увидите, что экземпляр в памяти не был затронут.
Но сам экземпляр db.Property
является дескриптором - его упаковка во встроенный property
(совершенно другой дескриптор) не будет хорошо работать с хранилищем данных (например, вы не можете писать запросы GQL основанные на именах полей, которые на самом деле не являются экземплярами db.Property
, а являются экземплярами property
- эти поля не в хранилище данных!).
Поэтому, если вы хотите работать с хранилищем данных и для экземпляров Model
, которые никогда не были в хранилище данных и обратно, вам придется выбрать two имена для того, что логически «одно и то же» поле - одно - это имя атрибута, который вы будете использовать в экземплярах модели в памяти, и этот может быть встроенным property
; другой - это имя атрибута, который заканчивается в хранилище данных, и он должен быть экземпляром db.Property
подкласса , а - это второе имя, которое вам нужно будет использовать в запросах , Конечно, методы, лежащие в основе первого имени, должны читать и писать второе имя, но вы не можете просто «спрятать» последнее, потому что это имя будет в хранилище данных, и поэтому это имя будет иметь смысл для запросы!