GAE / Python: имя_коллекции не работает с полимоделью?

#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, но вам потребуется несколько фильтров неравенства, чтобы исключить все дочерние классы. Обходным путем было бы вручную включить имя класса в качестве значения по умолчанию в базовой модели и установить другое значение по умолчанию для дочерних моделей. Тогда вы могли бы отфильтровать это.