Aby uzyskać metodę as_dict
na wszystkich moich klas użyłem Mixin
klasę która wykorzystuje techniki opisane przez Ants Aasma.
class BaseMixin(object):
def as_dict(self):
result = {}
for prop in class_mapper(self.__class__).iterate_properties:
if isinstance(prop, ColumnProperty):
result[prop.key] = getattr(self, prop.key)
return result
a następnie używać go w ten sposób w swoich klasach
class MyClass(BaseMixin, Base):
pass
ten sposób można wywołać następujące na wystąpienie MyClass
.
> myclass = MyClass()
> myclass.as_dict()
Mam nadzieję, że to pomoże.
Grałem arround z tym nieco dalej, tak naprawdę potrzebne, aby uczynić moje instancji jako dict
jako postaci HAL object z jego linki do pokrewnych przedmiotów. Dodałem tutaj tę małą magię, która będzie indeksować wszystkie właściwości klasy takie same jak wyżej, z tą różnicą, że będę się wczołgać głębiej w właściwości Relaionship
i automatycznie wygeneruję dla nich links
.
Należy pamiętać, że to będzie działać tylko dla relacji mieć jeden klucz podstawowy
from sqlalchemy.orm import class_mapper, ColumnProperty
from functools import reduce
def deepgetattr(obj, attr):
"""Recurses through an attribute chain to get the ultimate value."""
return reduce(getattr, attr.split('.'), obj)
class BaseMixin(object):
def as_dict(self):
IgnoreInstrumented = (
InstrumentedList, InstrumentedDict, InstrumentedSet
)
result = {}
for prop in class_mapper(self.__class__).iterate_properties:
if isinstance(getattr(self, prop.key), IgnoreInstrumented):
# All reverse relations are assigned to each related instances
# we don't need to link these, so we skip
continue
if isinstance(prop, ColumnProperty):
# Add simple property to the dictionary with its value
result[prop.key] = getattr(self, prop.key)
if isinstance(prop, RelationshipProperty):
# Construct links relaions
if 'links' not in result:
result['links'] = {}
# Get value using nested class keys
value = (
deepgetattr(
self, prop.key + "." + prop.mapper.primary_key[0].key
)
)
result['links'][prop.key] = {}
result['links'][prop.key]['href'] = (
"/{}/{}".format(prop.key, value)
)
return result
Zwróć uwagę, że '__table__.columns' podaje nazwy pól SQL, a nie nazwy atrybutów używanych w definicjach ORM (jeśli są one różne). –
Czy mogę zalecić zmianę ''_sa_'! = K [: 4]' na 'not k.startswith ('_ sa _')'? –
Nie trzeba pętli z inspect: 'inspect (JobStatus) .columns.keys()' – kirpit