Apakah ada cara sederhana untuk beralih pada pasangan nama dan nilai kolom?
Versi saya dari sqlalchemy adalah 0.5.6
Berikut adalah contoh kode tempat saya mencoba menggunakan dict (baris), tetapi ia melempar pengecualian, TypeError: objek 'Pengguna' tidak dapat diubah
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)
Menjalankan kode ini pada output sistem saya:
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
python
sqlalchemy
Anurag Uniyal
sumber
sumber
sqlalchemy.util.KeyedTuple
yang merupakan objek baris dari judul pertanyaan. Namun kueri dalam pertanyaan menggunakan kelas model (dipetakan) sehingga jenis objek baris adalah kelas model, bukansqlalchemy.util.KeyedTuple
.Jawaban:
Anda dapat mengakses internal
__dict__
objek SQLAlchemy, seperti berikut ::sumber
dictret = dict(row.__dict__); dictret.pop('_sa_instance_state', None)
__dict__
termasuk_sa_instance_state
entri yang kemudian harus dihapus. jika Anda memutakhirkan ke versi masa depan dan atribut lainnya ditambahkan, Anda mungkin harus kembali dan menanganinya secara manual. jika Anda hanya menginginkan data kolom (misalnya, untuk mengambil daftar instance dari kueri dan meletakkannya dalam bingkai data panda) maka{col.name: getattr(self, col.name) for col in self.__table__.columns}
seperti dijawab oleh Anurag Uniyal (dengan koreksi penting dari komentar untuk jawaban itu) tampaknya lebih ringkas dan salah- bukti.dict(u)
dan dengan benar menyatakan bahwa ia melempar aTypeError
.Saya tidak bisa mendapatkan jawaban yang baik jadi saya menggunakan ini:
Sunting: jika fungsi di atas terlalu panjang dan tidak cocok untuk beberapa selera di sini adalah satu liner (python 2.7+)
sumber
return dict((col, getattr(row, col)) for col in row.__table__.columns.keys())
,.row2dict = lambda row: dict((col, getattr(row, col)) for col in row.__table__.columns.keys())
dapat membuatnya menjadi liner nyata, tetapi saya lebih suka kode saya dapat dibaca, pendek secara horizontal, panjang secara vertikalx = Column('y', Integer, primary_key=True)
,? Tidak ada solusi yang berfungsi dalam kasus ini.return {c.name: getattr(self, c.name) for c in self.__table__.columns}
Sesuai @zzzeek dalam komentar:
sumber
query(MyModel).all()
: Objek MyModel tidak dapat diubah.Dalam SQLAlchemy v0.8 dan yang lebih baru, gunakan sistem inspeksi .
Perhatikan bahwa itu
.key
adalah nama atribut, yang dapat berbeda dari nama kolom, misalnya dalam kasus berikut:Metode ini juga berfungsi untuk
column_property
.sumber
sqlalchemy.inspect(obj).unloaded
baris memiliki
_asdict()
fungsi yang memberikan dictsumber
seperti yang disebutkan @balki:
The
_asdict()
metode dapat digunakan jika Anda query bidang tertentu karena dikembalikan sebagai KeyedTuple .Sedangkan, jika Anda tidak menentukan kolom, Anda dapat menggunakan salah satu metode yang diusulkan lainnya - seperti yang disediakan oleh @charlax. Perhatikan bahwa metode ini hanya valid untuk 2.7+.
sumber
.first()
metode)?Pertanyaan lama, tetapi karena ini hasil pertama untuk "baris sqlalchemy untuk mendiktekan" di Google, ia pantas mendapatkan jawaban yang lebih baik.
Objek RowProxy yang dikembalikan SqlAlchemy memiliki metode items (): http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.RowProxy.items
Itu hanya mengembalikan daftar (kunci, nilai) tupel. Jadi seseorang dapat mengonversi baris menjadi dikte menggunakan yang berikut:
Dengan Python <= 2.6:
Dengan Python> = 2.7:
sumber
list_of_dicts = [dict(row.items()) for row in rows]
table_name_column_name
, jika Anda ingin nama yang berbeda (mis. Hanyacolumn_name
), gunakan.label
metode ini.session.query( MyTable.column_name.label('column_name'), ... )
Dengan asumsi fungsi berikut akan ditambahkan ke
class User
yang berikut ini akan mengembalikan semua pasangan nilai kunci dari semua kolom:tidak seperti jawaban yang lain, semua hanya atribut tersebut dari objek yang dikembalikan yang merupakan
Column
atribut di tingkat kelas objek. Oleh karena itu tidak ada_sa_instance_state
atau atribut SQLalchemy lainnya atau Anda tambahkan ke objek disertakan. ReferensiEDIT: Lupa untuk mengatakan, bahwa ini juga berfungsi pada Kolom bawaan.
hybrid_propery
perpanjanganJika Anda juga ingin menyertakan
hybrid_property
atribut berikut ini akan berfungsi:Saya berasumsi di sini bahwa Anda menandai Kolom dengan awal
_
untuk menunjukkan bahwa Anda ingin menyembunyikannya, baik karena Anda mengakses atribut denganhybrid_property
atau Anda tidak ingin menunjukkannya. ReferensiTipp
all_orm_descriptors
juga mengembalikan hybrid_method dan AssociationProxy jika Anda juga ingin memasukkannya.Keterangan untuk jawaban lain
Setiap jawaban (seperti 1 , 2 ) yang didasarkan pada
__dict__
atribut hanya mengembalikan semua atribut objek. Ini bisa menjadi atribut yang lebih banyak daripada yang Anda inginkan. Seperti saya sedih ini termasuk_sa_instance_state
atau atribut lain yang Anda tetapkan pada objek ini.Setiap jawaban (seperti 1 , 2 ) yang didasarkan pada
dict()
fungsi hanya bekerja pada objek baris SQLalchemy yang dikembalikan olehsession.execute()
bukan pada kelas yang Anda tentukan untuk bekerja, seperticlass User
dari pertanyaan.The jawaban pemecahan yang didasarkan pada
row.__table__.columns
pasti akan tidak bekerja.row.__table__.columns
berisi nama kolom dari Database SQL. Ini hanya bisa sama dengan nama atribut dari objek python. Jika tidak, Anda mendapatkanAttributeError
. Untuk jawaban (seperti 1 , 2 ) berdasarkanclass_mapper(obj.__class__).mapped_table.c
itu sama.sumber
sumber
Mengikuti jawaban @balki, karena SQLAlchemy 0.8 Anda dapat menggunakan _asdict (), tersedia untuk objek-objek KeyedTuple. Ini memberikan jawaban yang cukup mudah untuk pertanyaan awal. Hanya, ubah dalam contoh Anda dua baris terakhir (untuk loop) untuk yang satu ini:
Ini berfungsi karena dalam kode di atas Anda adalah objek dari kelas tipe KeyedTuple , karena .all () mengembalikan daftar KeyedTuple. Oleh karena itu ia memiliki metode _asdict () , yang dengan baik mengembalikan Anda sebagai kamus.
WRT jawabannya oleh @STB: AFAIK, dan di samping itu .all () kembali adalah daftar KeypedTuple. Oleh karena itu, di atas berfungsi baik jika Anda menentukan kolom atau tidak, selama Anda berurusan dengan hasil .all () seperti yang diterapkan pada objek kueri.
sumber
.all()
mengembalikan daftarUser
instance, jadi ini tidak berfungsi.User
contoh tidak memiliki_asdict
metode. Lihat gist.github.com/RazerM/2eff51571b3c70e8aeecd303c2a2bc8dEkspresi yang Anda iterasi melalui mengevaluasi ke daftar objek model , bukan baris. Jadi berikut ini adalah penggunaan yang benar dari mereka:
Apakah Anda benar-benar perlu mengubahnya menjadi dikt? Tentu, ada banyak cara, tetapi Anda tidak perlu ORM bagian dari SQLAlchemy:
Pembaruan : Lihatlah
sqlalchemy.orm.attributes
modul. Ini memiliki seperangkat fungsi untuk bekerja dengan keadaan objek, yang mungkin berguna bagi Anda, terutamainstance_dict()
.sumber
Lihat Jawaban Alex Brasetvik , Anda dapat menggunakan satu baris kode untuk menyelesaikan masalah
Di bawah bagian komentar Jawaban Alex Brasetvik, zzzeek pencipta SQLAlchemy menyatakan ini adalah "Metode yang Benar" untuk masalah tersebut.
sumber
resultproxy
?Anda dapat mencoba melakukannya dengan cara ini.
Itu menggunakan metode built-in dalam objek kueri yang mengembalikan objek diktoner objek kueri.
referensi: https://docs.sqlalchemy.org/en/latest/orm/query.html
sumber
_asdict()
metode bawaan yang pada dasarnya zip nama bidang dengan nilai bidang dan mengembalikan hasilnya sebagai kamus.u
dalam kasus saya adalah string, dan saya mendapatkan kesalahan `` Model 'objek tidak memiliki atribut' _asdict'` @hllau di bawah ini berfungsi untuk sayaSaya telah menemukan posting ini karena saya sedang mencari cara untuk mengubah baris SQLAlchemy menjadi dict. Saya menggunakan SqlSoup ... tapi jawabannya dibangun sendiri, jadi, jika itu bisa membantu seseorang, inilah dua sen saya:
sumber
RowProxy
(c
dalam jawaban ini) mematuhi protokol pemetaan, jadi Anda bisa menelepondict(c)
.Anda dapat mengonversi objek sqlalchemy ke kamus seperti ini dan mengembalikannya sebagai json / kamus.
Fungsi pembantu:
Fungsi Pengemudi:
sumber
Dua arah:
1.
2.
sumber
Dokumen menawarkan solusi yang sangat sederhana:
ResultRow._asdict()
sumber
Inilah cara Elixir melakukannya. Nilai dari solusi ini adalah memungkinkannya secara rekursif termasuk representasi kamus hubungan.
sumber
Dengan kode ini Anda juga dapat menambahkan kueri "filter" atau "gabung" dan ini berfungsi!
sumber
Itu seharusnya bekerja.
sumber
Saya memiliki variasi pada jawaban Marco Mariani, yang dinyatakan sebagai dekorator. Perbedaan utama adalah bahwa ia akan menangani daftar entitas, serta dengan aman mengabaikan beberapa jenis nilai pengembalian lainnya (yang sangat berguna saat menulis tes menggunakan mengejek):
sumber
Untuk melengkapi jawaban @Anurag Uniyal, berikut adalah metode yang akan mengikuti hubungan secara rekursif:
sumber
d[relationship.key] = to_dict(val,with_relationships) if val else None
Dengan python 3.8+, kita bisa melakukan ini dengan dataclass, dan
asdict
metode yang menyertainya:Kuncinya adalah menggunakan
@dataclass
dekorator, dan membubuhi keterangan setiap kolom dengan tipenya (: str
bagian dariname: str = Column(String)
garis).Perhatikan juga bahwa karena
email
tidak dijelaskan, itu tidak termasuk dalamquery_result_dict
.sumber
Saya seorang programmer Python yang baru dicetak dan mengalami masalah mendapatkan ke JSON dengan tabel Bergabung. Dengan menggunakan informasi dari jawaban di sini saya membangun sebuah fungsi untuk mengembalikan hasil yang masuk akal ke JSON di mana nama tabel dimasukkan untuk menghindari keharusan alias, atau membuat bidang bertabrakan.
Cukup berikan hasil kueri sesi:
test = Session (). query (VMInfo, Customer) .join (Customer) .order_by (VMInfo.vm_name) .limit (50) .offset (10)
json = sqlAl2json (tes)
sumber
jika kolom tabel model Anda bukan kolom mysql equie.
seperti :
Perlu digunakan:
jika Anda menggunakan cara ini, Anda bisa mendapatkan modified_time dan create_time keduanya adalah None
Karena nama Atribut Kelas tidak sama dengan penyimpanan kolom di mysql
sumber
Kembalikan konten ini: kelas:
.KeyedTuple
sebagai kamussumber
Demi semua orang dan saya sendiri, inilah cara saya menggunakannya:
sumber
Fungsi ini mungkin membantu. Saya tidak dapat menemukan solusi yang lebih baik untuk menyelesaikan masalah ketika nama atribut berbeda dari nama kolom.
sumber
Anda akan membutuhkannya di mana-mana dalam proyek Anda, saya apriciate @anurag menjawabnya berfungsi dengan baik. sampai saat ini saya menggunakannya, tetapi itu akan mengacaukan semua kode Anda dan juga tidak akan bekerja dengan perubahan entitas.
Alih-alih mencoba ini, mewarisi kelas kueri basis Anda di SQLAlchemy
setelah itu di mana pun Anda akan mendefinisikan objek Anda "as_dict" metode akan ada di sana.
sumber
Dalam sebagian besar skenario, nama kolom cocok untuk mereka. Tetapi mungkin Anda menulis kode seperti berikut:
the column.name "user_email" sementara nama field adalah "email", kolom.name tidak bisa berfungsi dengan baik seperti sebelumnya.
sqlalchemy_base_model.py
Saya juga menulis jawabannya di sini
sumber