#python #google-app-engine #google-cloud-datastore
#python #google-app-engine #google-облако-хранилище данных
Вопрос:
У меня возникли проблемы с использованием db.ReferenceProperty с полимоделью в GAE. Если у меня есть две модели, полученные из базовой полимодели, и каждая из них имеет ссылку на другую «контейнерную» модель, коллекции в контейнере содержат обе полимодели, а не только ту, которую вы ожидаете. Вот тестовый пример, который показывает проблему:
from google.appengine.ext import db
from google.appengine.ext.db import polymodel
class MyContainer(db.Model):
name = db.StringProperty(default='mycontainer', multiline=False)
class MyBaseModel(polymodel.PolyModel):
name = db.StringProperty(default='mybasemodel', multiline=False)
class MyModelOne(MyBaseModel):
container = db.ReferenceProperty(MyContainer, collection_name='model_ones')
class MyModelTwo(MyBaseModel):
container = db.ReferenceProperty(MyContainer, collection_name='model_twos')
print "Beginning test.n"
c = MyContainer(name="Container")
c.put()
one = MyModelOne(name="One", container=c)
two = MyModelTwo(name="Two", container=c)
one.put()
two.put()
print "Ones:"
for o in c.model_ones:
print o.name
print "nTwos:"
for o in c.model_twos:
print o.name
И вывод:
Beginning test.
Ones:
One
Two
Twos:
One
Two
Я что-то упускаю при настройке своих ссылочных свойств или это ожидаемое поведение?
Ответ №1:
Итак, глядя на источник SDK, кажется, что _ReverseReferenceProperty (который преобразует коллекции в объекты запроса) не предпринимает никаких попыток обрабатывать полимодели. Есть несколько связанных жалоб на отслеживание проблем, здесь и здесь .
IMO, если это известное ограничение, оно должно быть упомянуто где-нибудь в документах PolyModel.
Редактировать: обходной путь без сбора данных будет примерно таким:
for o in MyModelOne.all().filter('container =', c):
Комментарии:
1. Спасибо, это подтверждает то, что я вижу. Я согласен с тем, что документы отсутствуют, я мог бы сообщить об ошибке в этом. Ваш фильтр работает, это решение для меня. В моем примере выше, как бы я получил всю MyBaseModel без связанных MyModelOne и MyModelTwo?
MyBaseModel.all().filter("_class !=", "MyModelOne")
не работает.2. AFAIK, ты не можешь. Фильтрация для kind = MyBaseModel или class = MyBaseModel будет соответствовать всем подклассам.
filter("class !=", "MyModelOne")
следует исключить MyModelOne, но вам потребуется несколько фильтров неравенства, чтобы исключить все дочерние классы. Обходным путем было бы вручную включить имя класса в качестве значения по умолчанию в базовой модели и установить другое значение по умолчанию для дочерних моделей. Тогда вы могли бы отфильтровать это.