sqalchemy 모델의 정의된 열에 대한 반복 방법?
SQLAlchemy 모델에 정의된 열 목록을 반복하는 방법을 찾고 있었습니다.몇 가지 모델에 대한 직렬화 및 복사 방법을 작성하기 위해 필요합니다.순 obj.__dict__
SA 특정 항목이 많이 포함되어 있기 때문에.
나 수 있습니다.id
그리고.desc
이름은?
class JobStatus(Base):
__tablename__ = 'jobstatus'
id = Column(Integer, primary_key=True)
desc = Column(Unicode(20))
이 작은 경우에도 쉽게 다음을 만들 수 있었습니다.
def logme(self):
return {'id': self.id, 'desc': self.desc}
합니다를 합니다.dict
(큰 개체의 경우).
다음 기능을 사용할 수 있습니다.
def __unicode__(self):
return "[%s(%s)]" % (self.__class__.__name__, ', '.join('%s=%s' % (k, self.__dict__[k]) for k in sorted(self.__dict__) if '_sa_' != k[:4]))
SA 마법 속성은 제외되지만 관계는 제외되지 않습니다.그래서 기본적으로 그것은 의존성, 부모, 자녀 등을 적재할 수 있는데, 이것은 절대적으로 바람직하지 않습니다.
때문입니다.Base
은 , 을 있습니다.__table__
다음 작업을 수행할 수 있도록 합니다.
for c in JobStatus.__table__.columns:
print c
for c in JobStatus.__table__.foreign_keys:
print c
SQLchemy 매핑된 개체에서 테이블 속성을 검색하는 방법 - 유사한 질문을 참조하십시오.
Mike 편집 : Mapper.c, Mapper.map_table 등의 기능을 참조해 주세요.0.8 이상을 사용하는 경우 Mapper.attrs 및 관련 기능도 참조하십시오.
Mapper.attters의 예:
from sqlalchemy import inspect
mapper = inspect(JobStatus)
for column in mapper.attrs:
print column.key
맵퍼에서 정의된 속성 목록을 가져올 수 있습니다.사용자의 경우 ColumnProperty 객체에만 관심이 있습니다.
from sqlalchemy.orm import class_mapper
import sqlalchemy
def attribute_names(cls):
return [prop.key for prop in class_mapper(cls).iterate_properties
if isinstance(prop, sqlalchemy.orm.ColumnProperty)]
저는 이것이 오래된 질문이라는 것을 깨달았지만, 저는 방금 같은 요구사항을 발견했고 미래의 독자들에게 대안적인 해결책을 제시하고 싶습니다.
처럼, 이름은 Josh 처럼, 됩니다 SQL JobStatus.__table__.columns
, 그래서 원래의 필드 이름 id가 아닌 jobstatus.id 를 얻게 될 것입니다.그렇게 유용하지는 않습니다.
은 입니다를 입니다._data
전체 데이터를 포함하는 열 개체의 속성입니다.면을 .JobStatus.__table__.columns._data
.
{'desc': Column('desc', Unicode(length=20), table=<jobstatus>),
'id': Column('id', Integer(), table=<jobstatus>, primary_key=True, nullable=False)}
에 .JobStatus.__table__.columns.keys()
좋은 깨끗한 목록을 얻을 수 있습니다.
['id', 'desc']
하면 SQLLchemy 의를 할 수 __mapper__
클래스 맵퍼를 얻을 수 있는 속성입니다.매핑된 모든 특성(관계 포함)을 가져오려면:
obj.__mapper__.attrs.keys()
합니다를 합니다.obj.__mapper__.column_attrs.keys()
기타 보기는 설명서를 참조하십시오.
https://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper.attrs
self.__table__.columns
는 특정 클래스에 정의된 열을 "유일하게" 제공합니다. 즉, 상속되지 않은 열을 제공합니다.모두 필요하시면 사용하세요.self.__mapper__.columns
. 당신의 예에서 나는 아마도 다음과 같은 것을 사용할 것입니다.
class JobStatus(Base):
...
def __iter__(self):
values = vars(self)
for attr in self.__mapper__.columns.keys():
if attr in values:
yield attr, values[attr]
def logme(self):
return dict(self)
받기 위해서는as_dict
내가 사용한 모든 수업의 방법.Mixin
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
그리고는 수업시간에 이렇게 사용합니다.
class MyClass(BaseMixin, Base):
pass
이 방법으로 다음을 호출할 수 있습니다.MyClass
.
> myclass = MyClass()
> myclass.as_dict()
도움이 되길 바랍니다.
이것을 가지고 좀 더 게임을 해봤습니다. 사실 저는 제 사례를 다음과 같이 표현해야 했습니다.dict
HAL 객체의 형태와 연관된 객체와의 링크.그래서 저는 여기에 이 작은 마법을 더했습니다. 위와 같은 클래스의 모든 속성을 기어오를 것입니다. 더 깊이 기어 들어가는 차이점이 있습니다.Relaionship
속성 및 생성links
이것들에 대해서는 자동으로.
기본 키가 하나인 관계에 대해서만 작동합니다.
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
self.__dict__
키가 속성 이름이고 개체의 값을 나타내는 dict를 반환합니다.
/!\ 보조 속성 '_sa_instance_state'가 있지만 사용자가 처리할 수 있습니다.
하는 동안에row._asdict()
대부분의 경우에 효과가 있었고, 객체 생성 과정 후에도 효과가 있는 접근 방식이 필요했습니다(db.session.add
등). 방법을 만들어 보자는 취지입니다.to_dict
e 사용getattr
.
class Inventory(db.Model):
__tablename__ = 'inventory'
id = db.Column('id', db.Integer(), primary_key=True)
date = db.Column('date', db.DateTime, nullable=False, default=datetime.utcnow)
item = db.Column('item', db.String(100))
def to_dict(self):
return {
column.name: getattr(self, column.name, None)
for column in Inventory.__table__.columns
}
record = Inventory(item="gloves")
db.session.add(record)
db.session.commit()
# print(record._asdict()) # << that doesn't work
print(record.to_dict()) # << that works as intended
이 솔루션은 열만 있는 dict를 생성합니다. 메타 특성이나 다음 주 업데이트 후 수동으로 치료해야 하는 모든 것은 없습니다.
추신. 플라스크-sqalchemy를 사용하지만 아이디어가 바뀌지는 않습니다.
모델의 특정 인스턴스의 데이터를 동적으로 얻고 싶습니다.저는 이 코드를 사용했습니다.
def to_json(instance):
# get columns data
data = {}
columns = list(instance.__table__.columns)
for column in columns:
data[column.name] = instance.__dict__[column.name]
return data
sqalchemy에서 json으로 모델을 매핑하려면 관계를 고려하여 이 코드를 사용합니다.
from sqlalchemy.orm import class_mapper
from sqlalchemy.ext.declarative import DeclarativeMeta
from sqlalchemy.orm import ColumnProperty
from sqlalchemy.orm import RelationshipProperty
class BaseMixin(object):
"""BaseMixin"""
__repr_hide = ["created_at", "updated_at"]
__insert_hide = []
@property
def _repr_hide(self):
return self.__repr_hide
@_repr_hide.setter
def _repr_hide(self, k):
self.__repr_hide.append(k)
@property
def _insert_hide(self):
return self.__insert_hide
@_insert_hide.setter
def _insert_hide(self, k):
self.__insert_hide.append(k)
def serialize(self, obj):
"""serialize from json"""
for k, v in obj.items():
if k in self.__repr_hide:
continue
if k in self.__insert_hide:
continue
if k in self.__table__.c.keys():
setattr(self, k, v)
return self
def deserialize(self, backref=None):
"""deserialize to json"""
res = dict()
for prop in class_mapper(self.__class__).iterate_properties:
if prop.key in self.__repr_hide:
continue
if isinstance(prop, ColumnProperty):
res[prop.key] = getattr(self, prop.key)
for prop in class_mapper(self.__class__).iterate_properties:
if prop.key in self.__repr_hide:
continue
if isinstance(prop, RelationshipProperty):
if prop.key == str(backref):
continue
key, value = prop.key, getattr(self, prop.key)
if value is None:
res[key] = None
elif isinstance(value.__class__, DeclarativeMeta):
res[key] = value.deserialize(backref=self.__table__)
else:
res[key] = [i.deserialize(backref=self.__table__) for i in value]
return res
def __iter__(self):
return iter(self.deserialize().items())
def __repr__(self):
vals = ", ".join(
"%s=%r" % (n, getattr(self, n))
for n in self.__table__.c.keys()
if n not in self._repr_hide
)
return "<%s={%s}>" % (self.__class__.__name__, vals)
이것이 오래된 질문이라는 것을 알지만, 그럼 다음은 어떻습니까?
class JobStatus(Base):
...
def columns(self):
return [col for col in dir(self) if isinstance(col, db.Column)]
열 :jobStatus.columns()
입니다가 요.['id', 'desc']
그런 다음 열과 값을 사용하여 루프를 통과하고 작업을 수행할 수 있습니다.
for col in jobStatus.colums():
doStuff(getattr(jobStatus, col))
언급URL : https://stackoverflow.com/questions/2537471/method-of-iterating-over-sqlalchemy-models-defined-columns
'programing' 카테고리의 다른 글
C 코드에서 ALSA 마스터 볼륨 설정 (0) | 2023.10.01 |
---|---|
JSON 데이터를 로드하여 select2 플러그인과 함께 사용하는 방법 (0) | 2023.10.01 |
Oracle에서 모든 필드가 고유한지 확인하는 방법은 무엇입니까? (0) | 2023.10.01 |
sql 명령을 통해 mysql 이진 로그가 활성화되는지 어떻게 알 수 있습니까? (0) | 2023.10.01 |
텍스트 파일에서 C의 배열로 숫자 읽기 (0) | 2023.10.01 |