Какая альтернатива свойству обратной ссылки в NDB?

Я прочитал этот вопрос и простой и четкий ответ, но в моем случае это бесполезно, потому что ответ не учитывает вложенный for. пожалуйста, посмотрите код:

class SuperCat(ndb.Model):

class Category(ndb.Model):
  supercat = ndb.KeyProperty(kind=SuperCat)

class SubCat(ndb.Model):
  category = ndb.KeyProperty(kind=Category)

обработчик:

Categories = ndb.gql("SELECT * FROM Category WHERE supercat = :1", supercat_key)
self.generate('supercat.html', {'Categories': Categories})

в шаблоне со старым db.Model и свойством обратной ссылки этого достаточно:

{{ for Category in Categories }}
  {{ for SubCat in Category.subcat_set }} # this is the back-reference in action

Какова столь же простая альтернатива для обслуживания такой структуры данных?


person Giovanni Di Noia    schedule 20.06.2012    source источник
comment
кажется, что Структурированные свойства — хорошая отправная точка..   -  person Giovanni Di Noia    schedule 22.06.2012


Ответы (1)


Давайте посмотрим на это системно. Во-первых, руководство по переводу db->ndb сообщает нам, что запрос, возвращающий экземпляры SubCategory для данного экземпляра Category составляет:

  subcats_query = SubCategory.query(SubCategory.category == cat.key)

(Обратите внимание, что я использую имена в нижнем регистре для экземпляров/сущностей и CapWords для классов/моделей. Таким образом, кошка является сущностью категории.)

Итак, в Python мы бы написали ваш двойной цикл следующим образом:

  for cat in categories:
    for subcat in SubCat.query(SubCat.category == cat.key):
      ...blah...

Чтобы превратить это во что-то, что легко доступно из шаблона, давайте определим новый метод в классе Category:

  class Category(ndb.Model):

    supercat = ndb.KeyProperty(kind=SuperCat)

    def subcat_set(self):
      return SubCat.query(SubCat.category == self.key)

Обратите внимание, что это метод; в Python вы должны назвать это:

  for cat in categories:
    for subcat in cat.subcat_set():
      ...blah...

Но в шаблоне вы можете (должны) исключить синтаксис вызова (), чтобы получить то, что хотите:

  {{ for cat in categories }}
    {{ for subcat in cat.subcat_set }}
      ...blah...

Попробуйте!

person Guido van Rossum    schedule 23.06.2012
comment
работает! но только с () в шаблоне. без () я получаю TypeError: объект «instancemethod» не повторяется. - person Giovanni Di Noia; 23.06.2012
comment
Какую систему шаблонов вы используете? Я думал, что Django автоматически вызывает callables. Но, может быть, Jinja2 этого не делает? Если вам не нравится (), вы можете украсить метод @property (строчная буква «p», встроенная функция Python). - person Guido van Rossum; 23.06.2012