Как получить все свойства класса (в Python) полимодели GAE, в том числе определенные через @property

Я использую полимодель Google App Engine для моделирования данных, которые могут иметь более одного экземпляра свойства - например, у контакта может быть несколько телефонных номеров. Скажи, что это моя установка:

class Foo(polymodel.PolyModel):
    some_prop = ndb.StringProperty()

    @property
    def bar(self):
        return Bar.query(Bar.foo == self.key)

class Bar(ndb.Model):
    foo = ndb.KeyProperty(kind = Foo)
    other_prop= ndb.StringProperty()

(Я получил этот подход после прочтения этой статьи GAE по моделированию данных: https://developers.google.com/appengine/articles/modeling)

Теперь, когда я делаю:

Foo._properties

Я получаю доступ только к следующему:

{'some_prop': StringProperty('some_prop'), 
 'class': _ClassKeyProperty('class', repeated=True)}

Есть ли способ получить доступ ко ВСЕМ свойствам, в том числе определенным с помощью @property?

Большое спасибо за любую помощь или понимание того, где я иду не так. - Ли

ОБНОВЛЕНИЕ: Основываясь на отличном ответе @FastTurle, я теперь добавил метод класса, который возвращает оба свойства класса, а также методы, помеченные как свойства через @property:

def props(self):
    return dict(self._properties.items() +  \
                   {attr_name:getattr(self,attr_name) for \
                    attr_name, attr_value in \
                    Foo.__dict__.iteritems() if \
                    isinstance(attr_value,property)}.items())

1 ответ

Решение

Выполнение Foo._properties должен получить доступ к любым атрибутам, которые вы определяете на своем polymodel.PolyModel которые наследуют от google.appengine.ext.db.Property,

Это означает, что KeyProperty, StringPropertyи т.д... появится в Foo._propertiesтак что я предполагаю, что теперь вам нужно найти все методы, украшенные property,

К счастью, это не так сложно. Во-первых, быстрый уклон в декораторы (простите, если вы уже знаете это).

В питоне декораторы являются просто синтаксическим сахаром. Например, эти два метода приводят к одному и тому же:

@property
def bar(self):
    pass

def bar(self):
    pass
bar = property(bar)

К счастью для нас, property(obj) возвращает новый property объект. Это также означает, что @property возвращает property объект также. Вы можете думать о property как класс! И, наконец, можно использовать isinstance(bar, property) увидеть, если bar это собственность.

Наконец, мы можем использовать это, изучив каждый из Fooатрибуты и выбирая только те, которые property экземпляров.

for attr_name, attr_value in Foo.__dict__.iteritems():
    if isinstance(attr_value, property):
        print attr_name, attr_value

# bar, <property object at ...>
Другие вопросы по тегам