Konvertuoti sqlalchemy eilutės objektą į python dict

Ar yra paprastas būdas kartoti per stulpelių pavadinimų ir vertybių poras?

Mano versija sqlalchemy - 0.5.6

Čia pateikiamas kodo pavyzdys, kuriuo bandžiau naudoti diktą (eilutę), tačiau jis išmeta išimtį, TypeError: naudotojo objektas nėra pasikartojantis

 import sqlalchemy from sqlalchemy import * from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker print "sqlalchemy version:",sqlalchemy.__version__ engine = create_engine('sqlite:///:memory:', echo=False) metadata = MetaData() users_table = Table('users', metadata, Column('id', Integer, primary_key=True), Column('name', String), ) metadata.create_all(engine) class User(declarative_base()): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String) def __init__(self, name): self.name = name Session = sessionmaker(bind=engine) session = Session() user1 = User("anurag") session.add(user1) session.commit() # uncommenting next line throws exception 'TypeError: 'User' object is not iterable' #print dict(user1) # this one also throws 'TypeError: 'User' object is not iterable' for u in session.query(User).all(): print dict(u) 

Šio kodo vykdymas mano sistemoje išeina:

 sqlalchemy version: 0.5.6 Traceback (most recent call last): File "untitled-1.py", line 37, in <module> print dict(u) TypeError: 'User' object is not iterable 
176
24 дек. „Anurag Uniyal“ nustatytas 24 d. 2009-12-24 15:42 '09 15:42 2009-12-24 15:42
@ 32 atsakymai
  • 1
  • 2

Aš negalėjau gauti gero atsakymo, todėl naudoju tai:

 def row2dict(row): d = {} for column in row.__table__.columns: d[column.name] = str(getattr(row, column.name)) return d 

Redaguoti: jei aukščiau nurodyta funkcija yra per ilga ir netinka tam tikram skoniui, čia yra vienas įdėklas (python 2.7 +)

 row2dict = lambda r: {c.name: str(getattr(r, c.name)) for c in r.__table__.columns} 
118
25 дек. Atsakymą pateikė Anurag Uniyal . 2009-12-25 08:20 '09 8:20 am. 2009-12-25 08:20

Galite pasiekti SQLAlchemy objekto vidinį __dict__ objektą, pavyzdžiui:

 for u in session.query(User).all(): print u.__dict__ 
167
29 апр. atsakymas pateikiamas hllau 29 d. 2012-04-29 09:31 '12 at 9:31 am 2012-04-29 09:31

SQLAlchemy v0.8 ir naujesnėse versijose naudokite tikrinimo sistemą.

 from sqlalchemy import inspect def object_as_dict(obj): return {c.key: getattr(obj, c.key) for c in inspect(obj).mapper.column_attrs} user = session.query(User).first() d = object_as_dict(user) 

Atminkite, kad .key yra atributo pavadinimas, kuris gali skirtis nuo stulpelio pavadinimo, pavyzdžiui, tokiu atveju:

 class_ = Column('class', Text) 

Šis metodas veikia ir „ column_property .

63
20 мая '16 в 18:32 2016-05-20 18:32 atsakymas duotas RazerM gegužės 20, 16 d. 18:32 2016-05-20 18:32
 for row in resultproxy: row_as_dict = dict(row) 
50
24 дек. Alex Brasetvik atsakymas gruodžio 24 d. 2009-12-24 15:45 '09 15:45 2009-12-24 15:45
Stygos

turėti _asdict() funkciją, kuri _asdict()

 In [8]: r1 = db.session.query(Topic.name).first() In [9]: r1 Out[9]: (u'blah') In [10]: r1.name Out[10]: u'blah' In [11]: r1._asdict() Out[11]: {'name': u'blah'} 
29
09 янв. Atsakymas pateikiamas balki 09 jan. 2014-01-09 22:53 '14, 10:53 AM 2014-01-09 22:53

kaip @balki paminėjo:

_asdict() metodas gali būti naudojamas, jei prašote konkretaus lauko, nes jis grąžinamas kaip „ KeyedTuple“ .

 In [1]: foo = db.session.query(Topic.name).first() In [2]: foo._asdict() Out[2]: {'name': u'blah'} 

Jei nenurodysite stulpelio, galite naudoti vieną iš kitų siūlomų metodų - pvz., @Charlax pateiktą metodą. Atkreipkite dėmesį, kad šis metodas galioja tik 2,7 +.

 In [1]: foo = db.session.query(Topic).first() In [2]: {x.name: getattr(foo, x.name) for x in foo.__table__.columns} Out[2]: {'name': u'blah'} 
15
15 июля '14 в 3:47 2014-07-15 03:47 atsakymas buvo pateiktas Sam Bourne'ui liepos 14 d. 14 d. 3:47 2014-07-15 03:47

Senas klausimas, bet kadangi tai yra pirmasis „sqlalchemy eilutės diktuoti“ rezultatas „Google“, jis nusipelno geresnio atsakymo.

„SqlAlchemy“ grąžintas „RowProxy“ objektas turi elementų () metodą: http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.RowProxy.items

Jis tiesiog grąžina eilių sąrašą (raktas, vertė). Taigi, galite konvertuoti eilutę į diktuoklę, naudodami:

Pythone <= 2,6:

 rows = conn.execute(query) list_of_dicts = [dict((key, value) for key, value in row.items()) for row in rows] 

Pythone> = 2,7:

 rows = conn.execute(query) list_of_dicts = [{key: value for (key, value) in row.items()} for row in rows] 
14
28 окт. atsakymas pateikiamas fgasparini 28 oct. 2016-10-28 00:00 '16 at 0:00 2016-10-28 00:00
 from sqlalchemy.orm import class_mapper def asdict(obj): return dict((col.name, getattr(obj, col.name)) for col in class_mapper(obj.__class__).mapped_table.c) 
12
16 марта '10 в 16:24 2010-03-16 16:24 atsakymą pateikė Marco Mariani kovo 16 d., 16:24, 2010-03-16 16:24

Po @balki atsakymo su SQLAlchemy 0.8 galite naudoti _asdict (), prieinamą KeyedTuple objektams. Tai suteikia gana paprastą atsakymą į pradinį klausimą. Tiesiog pakeiskite savo pavyzdį paskutines dvi eilutes (kilpa):

 for u in session.query(User).all(): print u._asdict() 

Tai veikia, nes aukščiau pateiktame kode u yra KeyedTuple tipo klasės objektas , nes .all () grąžina KeyedTuple sąrašą. Todėl jame yra _asdict () metodas, kuris puikiai grąžina žodyną.

WRT atsako @STB: AFAIK, anikong, kad .all () grąžina KeypedTuple sąrašą. Todėl pirmiau minėti veiksmai, jei nurodote stulpelį arba ne, jei susiduriate su užklausos objekto .all () rezultatu.

10
22 авг. atsakymas, kurį pateikė jgbarah rugpjūčio 22 d 2014-08-22 14:37 '14, 14:37, 2014-08-22 14:37

Pakartotinė išraiška apskaičiuoja modelių objektų, o ne styginių, sąrašą. Todėl jų tinkamas naudojimas:

 for u in session.query(User).all(): print u.id, u.name 

Ar jums tikrai reikia juos paversti diktais? Žinoma, yra daug būdų, tačiau jums nereikia SQLAlchemy ORM dalies:

 result = session.execute(User.__table__.select()) for row in result: print dict(row) 

Atnaujinti . Pažvelkite į modulį „ sqlalchemy.orm.attributes . Ji turi funkcijų rinkinį, skirtą dirbti su objekto būsena, kuri jums gali būti naudinga, ypač instance_dict() .

8
25 дек. Denis Otkidach atsakymas gruodžio 25 d 2009-12-25 08:42 '09 8:42 2009-12-25 08:42

Darant prielaidą, kad class User bus priskirtos šios funkcijos, toliau pateikiamos visos visų stulpelių raktų vertės poros:

 def columns_to_dict(self): dict_ = {} for key in self.__mapper__.c.keys(): dict_[key] = getattr(self, key) return dict_ 

skirtingai nei kiti atsakymai, viskas, bet tik tie objektų atributai, kurie yra Column atributai objekto klasės lygmenyje, grąžinami. Todėl _sa_instance_state arba bet kuris kitas SQLalchemy atributas neįtrauktas, arba įtraukiate jį į objektą. Nuoroda

EDIT: Pamirškite pasakyti, kad tai taip pat veikia su paveldimais stulpeliais.

hybrid_propery plėtinys

Jei taip pat norite įtraukti „ hybrid_property atributus, tai veiks:

 from sqlalchemy import inspect from sqlalchemy.ext.hybrid import hybrid_property def publics_to_dict(self) -> {}: dict_ = {} for key in self.__mapper__.c.keys(): if not key.startswith('_'): dict_[key] = getattr(self, key) for key, prop in inspect(self.__class__).all_orm_descriptors.items(): if isinstance(prop, hybrid_property): dict_[key] = getattr(self, key) return dict_ 

Darau prielaidą, kad stulpeliai pažymėti pradiniu _ norėdami nurodyti, kad norite juos paslėpti, nes prieigą prie atributo naudojate hybrid_property , arba tiesiog nenorite jų parodyti. Nuoroda

Tipp all_orm_descriptors taip pat grąžina hybrid_method ir AssociationProxy, jei taip pat norite juos įgalinti.

Pastabos kitiems atsakymams

Kiekvienas atsakymas (pavyzdžiui, 1 , 2 ), pagrįstas atributu __dict__ , tiesiog grąžina visus objekto atributus. Tai gali būti daug daugiau atributų, nei norite. Kaip ir aš, tai apima _sa_instance_state arba bet kurį kitą šį objektą apibrėžtą atributą.

Kiekvienas atsakymas (pvz., 1 , 2 ), pagrįstas diktavimu dict() veikia tik SQLalchemy eilutės objektuose, kuriuos grąžina sesija.execute session.execute() , o ne klasėms, kurias apibrėžiate darbui, pvz., class User iš klausimo.

Atsakymas pagal row.__table__.columns tikrai neveiks. row.__table__.columns yra SQL duomenų bazės stulpelių pavadinimai. Jie gali būti lygūs tik python objekto atributų pavadinimui. Jei ne, gausite „ AttributeError . Atsakymai (pvz., 1 , 2 ), pagrįsti class_mapper(obj.__class__).mapped_table.c yra tas pats.

7
17 мая '15 в 0:03 2015-05-17 00:03 Atsakymą F.Raabas pateikė gegužės 15 d., 15 val. 0:03 2015-05-17 00:03

Radau šį įrašą, nes ieškojau būdų konvertuoti SQLAlchemy eilutę į diktu. Aš naudoju SqlSoup ... bet atsakymą sukūrė pats, taigi, jei jis gali padėti kažkas čia, mano du centai:

 a = db.execute('select * from acquisizioni_motes') b = a.fetchall() c = b[0] # and now, finally... dict(zip(c.keys(), c.values())) 
7
04 авг. atsakymą pateikė Mychot sad 04 rug . 2012-08-04 19:31 '12 at 7:31 pm 2012-08-04 19:31

Alex Brasetvik“ atsakymas , galite išspręsti problemą naudodami vieną kodo eilutę.

 row_as_dict = [dict(row) for row in resultproxy] 

Alex Brasetvik komentarų skyriuje Atsakymas, zzzeek, ​​SQLAlchemy kūrėjas, pareiškė, kad tai yra „teisingas metodas“ problemai.

6
03 июля '17 в 13:26 2017-07-03 13:26 atsakymas pateikiamas „ NorWay“ liepos 03 d. 17, 13:26 2017-07-03 13:26

Tokiu būdu galite konvertuoti sqlalchemy objektą į žodyną ir grąžinti jį kaip json / žodyną.

Pagalbinės funkcijos:

 import json from collections import OrderedDict def asdict(self): result = OrderedDict() for key in self.__mapper__.c.keys(): if getattr(self, key) is not None: result[key] = str(getattr(self, key)) else: result[key] = getattr(self, key) return result def to_array(all_vendors): v = [ ven.asdict() for ven in all_vendors ] return json.dumps(v) 

Vairuotojo funkcija:

 def all_products(): all_products = Products.query.all() return to_array(all_products) 
3
03 мая '18 в 10:49 2018-05-03 10:49 atsakymas pateikiamas Chirag Vora 03 gegužės 18 d. 10:49 2018-05-03 10:49

Tai daro Elixir. Šio sprendimo reikšmė yra ta, kad ji leidžia rekursiškai įtraukti žodyno atstovavimą santykiams.

2
02 апр. atsakymas pateikiamas argentpepper 02 Apr. 2012-04-02 02:09 '12, 02:09 2012-04-02 02:09

Su šiuo kodu galite pridėti prie savo užklausos „filtrą“ arba „prisijungti“ ir šį darbą!

 query = session.query(User) def query_to_dict(query): def _create_dict(r): return {c.get('name'): getattr(r, c.get('name')) for c in query.column_descriptions} return [_create_dict(r) for r in query] 
2
05 нояб. atsakymą pateikė Yakir Tsuberi, lapkričio 5 d. 2017-11-05 12:39 '17 at 12:39 2017-11-05 12:39

Dokumentai yra labai paprastas sprendimas: ResultRow._asdict()

 def to_array(rows): return [r._asdict() for r in rows] def query(): data = session.query(Table).all() return to_array(data) 
2
06 сент. Atsakymą pateikė JB 06 Sep. 2018-09-06 18:55 '18, 18:55 pm 2018-09-06 18:55
 class User(object): def to_dict(self): return dict([(k, getattr(self, k)) for k in self.__dict__.keys() if not k.startswith("_")]) 

Tai turėtų veikti.

1
10 февр. Atsakymas duotas Singletoned 10 Feb. 2010-02-10 17:07 '10, 17:07, 2010-02-10 17:07

Du būdai:

1.

 for row in session.execute(session.query(User).statement): print(dict(row)) 

2

 selected_columns = User.__table__.columns rows = session.query(User).with_entities(*selected_columns).all() for row in rows : print(row._asdict()) 
1
07 февр. atsakymas pateiktas FrostSigh 07 vasaris. 2018-02-07 02:57 '18 at 2:57 2018-02-07 02:57

Turiu atsakymą už Marco Mariani, išreikštą kaip dekoratorius. Pagrindinis skirtumas yra tas, kad jis tvarkys objektų sąrašus ir taip pat yra saugu ignoruoti kai kurias kitas grąžinimo vertes (kurios yra labai naudingos rašant bandymus naudojant šautuvus):

 @decorator def to_dict(f, *args, **kwargs): result = f(*args, **kwargs) if is_iterable(result) and not is_dict(result): return map(asdict, result) return asdict(result) def asdict(obj): return dict((col.name, getattr(obj, col.name)) for col in class_mapper(obj.__class__).mapped_table.c) def is_dict(obj): return isinstance(obj, dict) def is_iterable(obj): return True if getattr(obj, '__iter__', False) else False 
1
28 июля '10 в 20:32 2010-07-28 20:32 Atsakymą pateikė Chris R , liepos 28 d. 10, 20:32 2010-07-28 20:32

Lengviausias būdas rasti (naudojant sqla 0.7.8):

 dictlist = [dict(row) for row in somequery.execute().fetchall()] 
0
24 февр. Atsakymas duotas Damien 24 vasario mėn. 2014-02-24 19:11 '14, 19:11, 2014-02-24 19:11

Aš esu naujas programuojamas programuotojas Pythone ir susiduriu su problemomis, susijusiomis su JSON su pridėtomis lentelėmis. Naudodamiesi čia gautais atsakymais, sukūriau funkciją, kad sugrąžintume pagrįstus JSON rezultatus, į kuriuos įtraukiami lentelės pavadinimai, vengiant slapyvardžio ar lauko susidūrimo.

Tiesiog praneškite sesijos užklausos rezultatui:

test = sesija (). užklausa (VMInfo, Klientas) .j. (Klientas) .order_by (VMInfo.vm_name) .limit (50) .offset (10)

json = sqlAl2json (testas)

 def sqlAl2json(self, result): arr = [] for rs in result.all(): proc = [] try: iterator = iter(rs) except TypeError: proc.append(rs) else: for t in rs: proc.append(t) dict = {} for p in proc: tname = type(p).__name__ for d in dir(p): if d.startswith('_') | d.startswith('metadata'): pass else: key = '%s_%s' %(tname, d) dict[key] = getattr(p, d) arr.append(dict) return json.dumps(arr) 
0
24 нояб. atsakymas suteiktas tknightowl lapkričio 24 d 2015-11-24 18:45 '15, 18:45 pm 2015-11-24 18:45

__dict__ be vidinių (pabrauktų) atributų gali būti naudojamas kaip greitas pataisymas.

 for u in session.query(User).all(): print({k: v for k, v in u.__dict__.items() if not k.startswith('_')}) 
0
17 янв. atsakymas duotas I159 17 sausio. 2019-01-17 19:12 „19, 19:12, 2019-01-17 19:12

jei jūsų modelio stulpelis neatitinka mysql stulpelio.

pavyzdžiui:

 class People: id: int = Column(name='id', type_=Integer, primary_key=True) createdTime: datetime = Column(name='create_time', type_=TIMESTAMP, nullable=False, server_default=text("CURRENT_TIMESTAMP"), default=func.now()) modifiedTime: datetime = Column(name='modify_time', type_=TIMESTAMP, server_default=text("CURRENT_TIMESTAMP"), default=func.now()) 

Turi būti naudojama:

  from sqlalchemy.orm import class_mapper def asDict(self): return {x.key: getattr(self, x.key, None) for x in class_mapper(Application).iterate_properties} 

jei naudojate šį metodą, galite gauti keitimo_pasirinkimo ir „sukurti“ laiko kaip Nėra

 {'id': 1, 'create_time': None, 'modify_time': None} def to_dict(self): return {c.name: getattr(self, c.name, None) for c in self.__table__.columns} 

Kadangi klasės atributo pavadinimas neatitinka stulpelio saugyklos MySQL

0
27 июня '18 в 12:34 2018-06-27 12:34 atsakymas 张小诚 birželio 27 d. 18 val. 12:34 pm 2018-06-27 12:34

Grąžinkite šio turinio: klasės: .KeyedTuple kaip žodyną

 In [46]: result = aggregate_events[0] In [47]: type(result) Out[47]: sqlalchemy.util._collections.result In [48]: def to_dict(query_result=None): ...: cover_dict = {key: getattr(query_result, key) for key in query_result.keys()} ...: return cover_dict ...: ...: In [49]: to_dict(result) Out[49]: {'calculate_avg': None, 'calculate_max': None, 'calculate_min': None, 'calculate_sum': None, 'dataPointIntID': 6, 'data_avg': 10.0, 'data_max': 10.0, 'data_min': 10.0, 'data_sum': 60.0, 'deviceID': u'asas', 'productID': u'U7qUDa', 'tenantID': u'CvdQcYzUM'} 
0
17 окт. atsakymas duotas Eds_k 17 okt. 2018-10-17 05:50 '18 at 5:50 2018-10-17 05:50

Dėl visų ir aš, taip aš naudoju tai:

 def run_sql(conn_String): output_connection = engine.create_engine(conn_string, poolclass=NullPool).connect() rows = output_connection.execute('select * from db1.t1').fetchall() return [dict(row) for row in rows] 
0
28 нояб. atsakymą pateikė bigdatamann, lapkričio 28 d. 2018-11-28 02:09 '18, 02:09 am 2018-11-28 02:09

Jūs galite pabandyti tai padaryti taip.

 for u in session.query(User).all(): print(u._asdict()) 

Jis naudoja integruotą metodą užklausos objekte, kuris grąžina diktofoninio užklausos objekto objektą.

Nuorodos: https://docs.sqlalchemy.org/en/latest/orm/query.html

0
21 янв. Atsakymą pateikė Enmanuel Medina 21 sausis. 2019-01-21 07:30 '19 , 7:30, 2019-01-21 07:30

Daugelyje scenarijų stulpelio pavadinimas yra tinkamas jiems. Bet galbūt jūs rašote tokį kodą:

 class UserModel(BaseModel): user_id = Column("user_id", INT, primary_key=True) email = Column("user_email", STRING) 

column.name "user_email", o lauko pavadinimas yra "email", stulpelis.name negali veikti kaip anksčiau.

sqlalchemy_base_model.py

taip pat rašykite atsakymą čia

-1
10 июля '15 в 3:46 2015-07-10 03:46 atsakymas pateikiamas kaka_ace liepos 10 d. 15 val. 3:46 2015-07-10 03:46

Sprendimas, kuris taip pat veikia su paveldėtomis klasėmis:

 from itertools import chain from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Mixin(object): def as_dict(self): tables = [base.__table__ for base in self.__class__.__bases__ if base not in [Base, Mixin]] tables.append(self.__table__) return {c.name: getattr(self, c.name) for c in chain.from_iterable([x.columns for x in tables])} 
-1
08 июня '16 в 17:11 2016-06-08 17:11 atsakymas pateikiamas magne4000 Birželio 08 '16, 17:11 2016-06-08 17:11

Čia yra paprastas būdas tai padaryti.

 row2dict = lambda r: dict(r.items()) 
-2
02 июня '13 в 10:54 2013-06-02 10:54 atsakymą pateikė vartotojo2444711 birželio 2 d. 13 val. 10:54 2013-06-02 10:54
  • 1
  • 2

Kiti klausimai apie arba Užduoti klausimą