স্ক্ল্যাচমি সারি বস্তুকে পাইথন ডিকে রূপান্তর করুন


240

কলামের নাম এবং মান জোড়ায় পুনরাবৃত্তি করার কোনও সহজ উপায় আছে?

স্ক্লাচেমির আমার সংস্করণটি 0.5.6

এখানে আমি নমুনা কোডটি চেষ্টা করেছি যেখানে আমি ডিক (সারি) ব্যবহার করার চেষ্টা করেছি, তবে এটি ব্যতিক্রম ছুঁড়ে ফেলেছে, টাইপআরার: 'ব্যবহারকারীর' অবজেক্টটি পুনরাবৃত্তিযোগ্য নয়

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)

আমার সিস্টেম আউটপুটগুলিতে এই কোডটি চালানো:

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

3
প্রশ্নের শিরোনাম নিজেই প্রশ্নের সাথে মেলে না। দস্তাবেজ অনুসারে ফলাফলগুলি সারিগুলি কোয়েরিতে ফিরে এসেছে যাতে একাধিক ORM সত্তা এবং / অথবা কলামের এক্সপ্রেশন থাকে এই শ্রেণীর ব্যবহার সারিগুলি ফেরত দেয়। যেখানে এই শ্রেণীর হয় sqlalchemy.util.KeyedTupleযা সারি বস্তুর প্রশ্ন শিরোনাম থেকে। তবে প্রশ্নের ক্যোয়ারী মডেল (ম্যাপযুক্ত) শ্রেণি ব্যবহার করে সুতরাং সারি বস্তুর প্রকারটি পরিবর্তিত মডেল শ্রেণি sqlalchemy.util.KeyedTuple
পাইওটর ডব্রোগস্ট

2
@ পাইওটারডব্রোগোস্ট প্রশ্নটি ২০০৯ সালের এবং স্কেলচেমি সংস্করণ ০.০.tions উল্লেখ করেছে
অনুরাগ

উত্তর:


232

আপনি __dict__নীচের মতো একটি এসকিউএলএলচেমি অবজেক্টের অভ্যন্তরীণ অ্যাক্সেস করতে পারেন :

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

24
এই থ্রেডের সেরা উত্তর, জানেন না যে প্রত্যেকে কেন আরও জটিল সমাধানগুলির প্রস্তাব দিচ্ছে।
ডেভ রাকস

92
এটি কমপক্ষে 0.7.9 সংস্করণে একটি অতিরিক্ত '_ এসএ_স্ট্যান্স_স্টেট' ক্ষেত্র দেয় gives
এলবিয়ার

21
সুতরাং এটি আরও ভাল হবে:dictret = dict(row.__dict__); dictret.pop('_sa_instance_state', None)
লাইফিং

6
এটি আদর্শ বলে মনে হচ্ছে না কারণ যেহেতু লোকেদের নির্দেশিত __dict__একটি _sa_instance_stateপ্রবেশ অন্তর্ভুক্ত রয়েছে যা অবশ্যই অপসারণ করতে হবে। আপনি যদি ভবিষ্যতের সংস্করণে আপগ্রেড হন এবং অন্যান্য বৈশিষ্ট্যগুলি যুক্ত করা হয় তবে আপনাকে ফিরে যেতে হবে এবং ম্যানুয়ালি সেগুলি মোকাবেলা করতে হতে পারে। যদি আপনি কেবল কলামের ডেটা চান (উদাহরণস্বরূপ, কোনও ক্যোয়ারী থেকে উদাহরণগুলির একটি তালিকা নিয়ে সেগুলি একটি পান্ডাস ডেটা ফ্রেমে ফেলে দিন) তবে {col.name: getattr(self, col.name) for col in self.__table__.columns}অনুরাগ ইউনিয়ালের উত্তর অনুসারে (সেই উত্তরের মন্তব্যে গুরুত্বপূর্ণ সংশোধন সহ) আরও দুটি সংঘাত এবং ত্রুটি- বলে মনে হচ্ছে প্রমাণ।
কেজি

14
এই উত্তরটি ভুল। প্রশ্ন এমনকি আছে dict(u)এবং সঠিকভাবে এটি একটি নিক্ষেপ TypeError
রেজার এম

146

আমি একটি ভাল উত্তর পেতে পারি না তাই আমি এটি ব্যবহার করি:

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

    return d

সম্পাদনা করুন: উপরের ফাংশনটি যদি দীর্ঘ হয় এবং কিছু স্বাদের জন্য উপযুক্ত না হয় তবে এখানে একটি লাইনার রয়েছে (পাইথন ২.7+)

row2dict = lambda r: {c.name: str(getattr(r, c.name)) for c in r.__table__.columns}

17
আরও সংক্ষেপে return dict((col, getattr(row, col)) for col in row.__table__.columns.keys()),।
আরজেন্টেপ্পার

4
@ আর্জেন্টপ্পি হ্যাঁ আপনি row2dict = lambda row: dict((col, getattr(row, col)) for col in row.__table__.columns.keys())এটিকে সত্যিকারের লাইনার হিসাবে তৈরি করতে পারেন তবে আমি আমার কোডটি পাঠযোগ্য, অনুভূমিকভাবে সংক্ষিপ্ত, উল্লম্বভাবে দীর্ঘ হতে পছন্দ করি
অনুরাগ ইউনিিয়াল

14
যদি আমার কলামটি একই নামের কোনও বৈশিষ্ট্যে নির্ধারিত না হয় তবে কী হবে? আইই x = Column('y', Integer, primary_key=True),? এই সমাধানগুলির কোনওটিই এই ক্ষেত্রে কাজ করে না।
বাটনস 840

13
drdaeman ঠিক, এখানে সঠিক স্নিপেট:return {c.name: getattr(self, c.name) for c in self.__table__.columns}
চার্লাক্স

5
এই উত্তরটি একটি অবৈধ অনুমান করে: কলামের নামগুলি অ্যাট্রিবিউট নামের সাথে মেলে না।
20:56

94

মন্তব্য হিসাবে @Zzeek অনুযায়ী:

নোট করুন যে এটি এসকিউএএলএলচেমির আধুনিক সংস্করণের সঠিক উত্তর, "সারি" একটি মূল সারি অবজেক্ট, কোনও ওআরএম-ম্যাপযুক্ত উদাহরণ নয়।

for row in resultproxy:
    row_as_dict = dict(row)

13
এরা বলছে 'XXX এর অবজেক্ট iterable নয়', আমি 0.5.6 ব্যবহার করছি, আমি session.query (Klass) .filter () দ্বারা পেতে সব ()।
অনুরাগ Uniyal

60
নোট করুন যে এটি এসকিউএএলএলচেমির আধুনিক সংস্করণের সঠিক উত্তর, "সারি" একটি মূল সারি অবজেক্ট, কোনও ওআরএম-ম্যাপযুক্ত উদাহরণ নয়।
zzzeek

48
আরও মনে রাখবেন যে zzzeek স্ক্লাচেমির স্রষ্টা।
খ্রিস্ট

1
কেউ কি এই একটি বিস্তারিত বলতে পারেন? আমি একজন নুব আছি না!
লামেই

1
একটি ORM- ম্যাপযুক্ত উদাহরণ বনাম একটি মূল সারি অবজেক্টের মধ্যে পার্থক্য কী? এটি এর থেকে সারিগুলিতে আমার পক্ষে কাজ করে না query(MyModel).all(): মাইমোডেল অবজেক্টটি পুনরাবৃত্তিযোগ্য নয়।
জোনাথন হার্টলি

81

এসকিউএএলএলএকমি v0.8 এবং আরও নতুনতে, পরিদর্শন ব্যবস্থাটি ব্যবহার করুন ।

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)

নোটটি .keyহ'ল বৈশিষ্ট্যের নাম, যা কলামের নাম থেকে পৃথক হতে পারে, যেমন নিম্নলিখিত ক্ষেত্রে:

class_ = Column('class', Text)

এই পদ্ধতিটিও কাজ করে column_property


@ ডুকডুগাল আমি মনে করি এটি v0.8 থেকে কাজ করে (যখন পরিদর্শন ব্যবস্থাটি যুক্ত করা হয়েছিল)।
রেজারএম

1
এটি স্ক্ল্যাচেমি ভি 2.0 এর সাথে কাজ করে। অন্যান্য উত্তর দেয় না।
থানহ

এটি মুলতুবি কলামগুলিতে বিবেচনা করে না
চিহ্নিত করুন

1
@ মার্ক এটি আমার কাছে পরিষ্কার নয় যে সেগুলি ডিফল্টরূপে বাদ দেওয়া উচিত। তবুও, আপনি চেক করতে পারবেন যে কীগুলি নেইsqlalchemy.inspect(obj).unloaded
রাজারম

5
@ এনগুইনথান এসকিউএলএলএকমি ভি 2.0 এর সাথে কাজ করা অস্তিত্বের কারণে বিশেষভাবে চিত্তাকর্ষক! সর্বশেষ (বিটা) প্রকাশটি v1.3.0b1।
মার্ক অ্যামেরি

39

সারিগুলির একটি _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'}

এটি বেসরকারী বলে মনে করা হয় এবং ভবিষ্যতের সংস্করণগুলিতে সম্ভবত মুছে ফেলা / পরিবর্তন করা যায়নি।
বালকি

2
@ বালকি এটি বেশ ভালভাবে নথিভুক্ত এবং যেমনটি খুব ব্যক্তিগত নয়। যদিও পাইথনের একটি অগ্রণী আন্ডারস্কোর এর সাধারণ অর্থ রয়েছে, তবে সম্ভবত এটি সম্ভবত টিউপল কীগুলির সাথে সংঘাত না করার জন্য ব্যবহৃত হয়।
ইলজা এভারিলä

5
এটি কেবল কিয়েডটপল এর সাথে কাজ করে, যা কেবল তখনই সারিটির নির্দিষ্ট ক্ষেত্রগুলি অনুসন্ধান করার সময় ফিরে আসে। উদাহরণস্বরূপ .query (টপিক.নাম) কেয়েডটুপল প্রদান করে, যখন .query (টপিক) একটি টপিক প্রদান করে, যার নেই ._াসক্ত () - ডিয়ার্প D কেবল নীচে এসটিবিদের উত্তর দেখেছি।
চাদ লো

20

যেমন @ বালকি উল্লেখ করেছেন:

_asdict()আপনি যদি একটি নির্দিষ্ট ক্ষেত্রটি জিজ্ঞাসা করছেন তবে পদ্ধতিটি কেয়েডটুপল হিসাবে ফিরিয়ে দেওয়া হলে এই পদ্ধতিটি ব্যবহার করা যেতে পারে ।

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

অন্যদিকে, আপনি যদি কোনও কলাম নির্দিষ্ট না করেন তবে আপনি প্রস্তাবিত অন্যান্য পদ্ধতির মধ্যে একটি ব্যবহার করতে পারেন - যেমন @ চার্ল্যাক্স সরবরাহ করেছেন। মনে রাখবেন যে এই পদ্ধতিটি কেবল 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'}

: পাইথন ORM বর্গ বৈশিষ্ট্যাবলী ডাটাবেসের কলাম থেকে বিভিন্ন নাম থাকে, তাহলে এই সমাধান চেষ্টা stackoverflow.com/questions/27947294/...
TaiwanGrapefruitTea

2
আসলে সব ক্ষেত্রেই জন্য একটি ভাল সমাধান এ sqlalchemy লেখক দ্বারা প্রদান করা হয় stackoverflow.com/a/27948279/1023033
TaiwanGrapefruitTea

যখন আমি এই চেষ্টা আমি ResultProxy বস্তুর কোন অ্যাট্রিবিউট '_asdict' হয়েছে পেতে
slashdottir

@ স্ল্যাশডটিটার, আপনি কি আপনার ক্যোয়ারী অবজেক্টটি চালাচ্ছেন ( .first()পদ্ধতিটি কল করছেন )?
স্যাম বোর্ন

1
এই উত্তরটি একটি অবৈধ অনুমান করে: কলামের নামগুলি অ্যাট্রিবিউট নামের সাথে অগত্যা মেলে না - রাজারএম এর উত্তর দেখুন।
পাইওটর ডব্রোগোস্ট

18

পুরানো প্রশ্ন, তবে যেহেতু গুগলে এটি "স্ক্যালচেমি সারি থেকে ডিক্ট" এর প্রথম ফলাফল এটি আরও ভাল উত্তরের দাবিদার।

RowProxy বস্তুর SqlAlchemy ফেরৎ যে আইটেম রয়েছে () পদ্ধতি: http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.RowProxy.items

এটি কেবল (কী, মান) টিউপসগুলির একটি তালিকা প্রদান করে। সুতরাং কেউ নিম্নলিখিতটি ব্যবহার করে একটি সারি ডিকায় রূপান্তর করতে পারে:

পাইথনে <= 2.6:

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

পাইথনে> = 2.7:

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

13
আপনি কেবল করতে পারেনlist_of_dicts = [dict(row.items()) for row in rows]
মার্কাস মেসকেনেন

একটি ছদ্মবেশটি হ'ল এসকিউএলএলচেমি ফলাফলের সেটগুলিতে যে কলামের নামগুলি ব্যবহার করে সেগুলি হ'ল table_name_column_name, যদি আপনি আলাদা আলাদা নাম চান (যেমন: ঠিক column_name), তবে .labelপদ্ধতিটি ব্যবহার করুন । session.query( MyTable.column_name.label('column_name'), ... )
আনিল

হাই, আমি এই ইস্যুটি পেয়ে যাচ্ছি আমাকে সাহায্য করুন * ডেটটাইম.ডেটটাইম (2018, 11, 24, 18, 52, 50) জেএসওএন সিরিয়ালযোগ্য নয় *
সারাভানন নন্ধন

13

নিম্নলিখিত ফাংশনগুলি ধরে নিলে যুক্ত করা হবে class User সমস্ত কলামের সমস্ত কী-মান জোড়গুলি ফিরে আসবে:

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

অন্যান্য উত্তরগুলির মত নয়, কেবলমাত্র বস্তুর সেই বৈশিষ্ট্যগুলিই ফিরে আসে যা বস্তুর Columnশ্রেণি স্তরে বৈশিষ্ট্য at সুতরাং না_sa_instance_state বা অন্য কোনও বৈশিষ্ট্য এসকিউএলএকচেমি বা আপনি বস্তুতে যুক্ত যুক্ত নয়। উল্লেখ

সম্পাদনা: বলতে ভুলবেন না যে এটি উত্তরাধিকার সূত্রে প্রাপ্ত কলামগুলিতেও কাজ করে।

hybrid_propery এক্সটেনশন

আপনি যদি hybrid_propertyবৈশিষ্ট্যগুলি অন্তর্ভুক্ত করতে চান তবে নিম্নলিখিতগুলি কাজ করবে:

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_

আমি এখানে ধরে নিয়েছি যে আপনি কলামগুলি একটি শুরুর _সাথে চিহ্নিত করে এটি চিহ্নিত করার জন্য যে আপনি সেগুলি আড়াল করতে চান, হয় কারণ আপনি কোনও দ্বারা কোনও অ্যাট্রিবিউটটি অ্যাক্সেস করেছেন hybrid_propertyবা আপনি কেবল সেগুলি দেখাতে চান না। উল্লেখ

টিপ্ all_orm_descriptors এছাড়াও আয় hybrid_method এবং AssociationProxy আপনি তাদের অন্তর্ভুক্ত করতে চান পারেন।

অন্যান্য উত্তরের মন্তব্য

প্রতিটি উত্তর ( 1 , 2 এর মতো ) যা __dict__গুণাবলীর উপর ভিত্তি করে কেবল অবজেক্টের সমস্ত বৈশিষ্ট্য প্রদান করে। এটি আপনার চাইলে আরও অনেকগুলি বৈশিষ্ট্য হতে পারে। যেমন আমি দুঃখ পেয়েছি এর মধ্যে অন্তর্ভুক্ত রয়েছে _sa_instance_stateবা অন্য কোনও বৈশিষ্ট্য যা আপনি এই বস্তুটিতে সংজ্ঞায়িত করেন।

ফাংশনের উপর ভিত্তি করে প্রতিটি উত্তর (যেমন 1 , 2 ) dict()কেবলমাত্র এসকিউএলচেমি সারি অবজেক্টগুলিতে কাজ session.execute()করে যা আপনি যে শ্রেণীর সাথে কাজ করার জন্য সংজ্ঞায়িত করেছেন ঠিক তেমন class Userপ্রশ্ন থেকেই নয়।

সমাধান উত্তর যার উপর ভিত্তি করে তৈরি row.__table__.columnsস্পষ্টভাবে হবে না হবে। row.__table__.columnsএসকিউএল ডাটাবেসের কলামের নাম রয়েছে। এই শুধুমাত্র পারেন পাইথন বস্তুর বৈশিষ্ট্যাবলী নাম সমান হতে। যদি না হয় আপনি একটি পাবেন AttributeError। উত্তরের জন্য ( 1 , 2 এর মতো ) এর ভিত্তিতে class_mapper(obj.__class__).mapped_table.cএকই।


12
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)

4
স্থানীয়_সামগ্রী এবং ম্যাপযুক্ত_সারণের মধ্যে পার্থক্য সম্পর্কে সচেতন হন। উদাহরণস্বরূপ, আপনি যদি আপনার ডিবিতে কিছু ধরণের টেবিলের উত্তরাধিকার প্রয়োগ করেন (tbl_employees> tbl_managers, tbl_employees> tbl_staff), আপনার ম্যাপ করা ক্লাসগুলিতে এটি (পরিচালক (কর্মচারী), কর্মী (কর্মচারী)) প্রতিফলিত হবে। maped_table.c আপনাকে বেস টেবিল এবং উত্তরাধিকার সারণী উভয়ের কলামের নাম দেবে। স্থানীয়_ টেবিল কেবলমাত্র আপনার (উত্তরাধিকার সূত্রে) সারণীর নাম দেয়।
মাইকেল একোকা

এটি '_ এসএ_ইনস্ট্যান্স_স্টেট' ফিল্ডটি দেওয়া এড়ায়, কমপক্ষে সংস্করণে 0.8+ এ।
ইভান সিরোকি

4
এই উত্তরটি একটি অবৈধ অনুমান করে: কলামের নামগুলি অ্যাট্রিবিউট নামের সাথে মেলে না।
রেজার এম

11

এসকিউএলএলচেমি 0.8 সাল থেকে @ বাল্কি উত্তর অনুসরণ করছেন আপনি কেয়েডটুপল অবজেক্টের জন্য উপলভ্য _াসক্ত () ব্যবহার করতে পারেন। এটি আসল প্রশ্নের একটি দুর্দান্ত সোজা উত্তর দেয়। কেবলমাত্র, আপনার উদাহরণটিতে এটির জন্য শেষ দুটি লাইন (লুপের জন্য) পরিবর্তন করুন:

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

এটি কাজ করে কারণ উপরের কোডে ইউ টাইপ শ্রেণীর কেয়েডটুপলের একটি অবজেক্ট , যেহেতু .all () কেয়েডটুপলের একটি তালিকা প্রদান করে। অতএব এটির পদ্ধতি _যুক্তি () রয়েছে , যা আপনাকে অভিধান হিসাবে সুন্দরভাবে ফিরিয়ে দেয়।

@ এসটিবি দ্বারা উত্তর ডাব্লুআরটি: এএফআইএইকি, আনথং যা। সমস্ত () রিটার্ন হ'ল কীপটেডআপেলের একটি তালিকা। অতএব, উপরের কাজগুলি হয় আপনি যদি একটি কলাম নির্দিষ্ট করেন বা না করেন, যতক্ষণ আপনি কোয়েরি অবজেক্টে প্রয়োগ না করে .all () এর ফলাফলের সাথে ডিল করছেন।


6
এটি অতীতে সত্য হতে পারে, তবে এসকিউএএলএলচেমি ভি 1.0 এ উদাহরণগুলির .all()একটি তালিকা ফেরত Userদেয়, সুতরাং এটি কার্যকর হয় না।
RazerM

@ রাজারম, দুঃখিত, তবে আপনি কী বলতে চাইছেন তা আমি বুঝতে পারি না। লুপের জন্য ব্যবহারকারীর উদাহরণগুলির তালিকাটি অবশ্যই সঠিকভাবে লুপ করা উচিত, সেগুলি (ইউ) অভিধানে রূপান্তর করা এবং তারপরে মুদ্রণ করা উচিত ...
জেগবারঃ

3
Userদৃষ্টান্তগুলির একটি _asdictপদ্ধতি নেই। Gist.github.com/RazerM/2eff51571b3c70e8aeecd303c2a2bc8d
রাজার এম

2
এখন আমি বুঝতে পেরেছি. ধন্যবাদ। কেয়েডটুপলের পরিবর্তে, এখন। সমস্ত () ব্যবহারকারীর বস্তুগুলি ফেরত দেয়। সুতরাং v1.0 এর সমস্যা (এবং আমি ধরে নিই) কীভাবে কোনও ব্যবহারকারী অবজেক্টের থেকে অভিধান পেতে হয়। স্পষ্টতার জন্য ধন্যবাদ।
jgbarah

10

আপনি যে অভিব্যক্তিটি পুনরাবৃত্তি করছেন তা সারি নয়, মডেল অবজেক্টের তালিকার জন্য মূল্যায়নের মাধ্যমে ঘটছে । সুতরাং নিম্নলিখিতটি তাদের সঠিক ব্যবহার:

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

আপনার কি সত্যই তাদের ডিক্সে রূপান্তর করতে হবে? অবশ্যই, অনেকগুলি উপায় রয়েছে তবে তারপরে আপনার এসকিউএলএলচেমির ORM অংশের প্রয়োজন হবে না:

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

আপডেট : sqlalchemy.orm.attributesমডিউলটি একবার দেখুন । এটা তোলে বস্তুর রাষ্ট্র সঙ্গে কাজ করার ফাংশন একটি সেট, যেগুলো বিশেষভাবে আপনার জন্য দরকারী হতে পারে, হয়েছে instance_dict()


2
আমি এগুলি ডিকে রূপান্তর করতে চাই, কারণ অন্য কিছু কোডের ডিক হিসাবে ডেটা প্রয়োজন, এবং আমি একটি জেনেরিক উপায় চাই কারণ কোনও মডেল অবজেক্টের কলামগুলি আমি জানি না
অনুরাগ ইউনিিয়াল

এবং আমি যখন তাদের কাছে হ্যান্ডেল পাই তখন কেবলমাত্র মডেল অবজেক্টগুলিতে অ্যাক্সেস থাকি তাই আমি সেশন.এক্কুট ইত্যাদি ব্যবহার করতে পারি না
অনুরাগ ইউনিয়াল

8

পড়ুন অ্যালেক্স Brasetvik এর উত্তর , আপনি সমস্যা সমাধানের জন্য কোডের এক লাইন ব্যবহার করতে পারেন

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

অ্যালেক্স ব্র্যাসেটভিকের উত্তরের মন্তব্য বিভাগের অধীনে এসকিউএলএলচেমির নির্মাতা zzzeek বলেছেন যে এটি সমস্যার "সঠিক পদ্ধতি"।


1
@ গ্রিননলাইন শিওর, অনুমোদনের মন্তব্যটি অ্যালেক্স ব্রাসেটভিকের উত্তরের অন্তর্গত। তার উত্তরের যোগসূত্রটি সম্পাদিত
নরওয়ে

কি resultproxy?
লামেই

8

আপনি এটি এইভাবে করার চেষ্টা করতে পারেন।

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

এটি ক্যোয়ারী অবজেক্টে একটি অন্তর্নির্মিত পদ্ধতি ব্যবহার করে যা কোয়েরি অবজেক্টের একটি স্বৈরশাসক বস্তু দেয়।

তথ্যসূত্র: https://docs.sqlalchemy.org/en/latest/orm/query.html


1
আরও কিছু ব্যাখ্যা সম্ভবত যোগ করতে চান?
Tiw

1
আসলে আরও কিছু বোঝাতে হবে না explain এটি ফলাফল অবজেক্টের একটি অন্তর্নির্মিত পদ্ধতি। সুতরাং আপনি সমস্ত ফলাফলের জন্য এটি করেন বা একক সারিতে, একটি অন্তর্নির্মিত _asdict()পদ্ধতি রয়েছে যা মূলত ক্ষেত্রের নামগুলি ক্ষেত্রের মানগুলি দিয়ে জিপ করে এবং অভিধান হিসাবে ফলাফলটি প্রদান করে।
ম্যাথু

খুব সংক্ষিপ্ত এবং আমি আশা করি এটি কাজ করেছে তবে uআমার ক্ষেত্রে একটি স্ট্রিং রয়েছে এবং আমি ত্রুটি পেয়েছি `` মডেল 'অবজেক্টটির কোনও বৈশিষ্ট্য নেই' _াসডিক্ট'` @ নীচে আমার পক্ষে কাজ করেছে
মোট জার্ট

7

আমি এই পোস্টটি খুঁজে পেয়েছি কারণ আমি একটি এসকিউএলএলচেমি সারি একটি ডিকে রূপান্তর করার জন্য একটি উপায় খুঁজছিলাম। আমি স্ক্যালসুপ ব্যবহার করছি ... তবে উত্তরটি আমার নিজের দ্বারা তৈরি করা হয়েছিল, সুতরাং, যদি এটি কাউকে আমার দুই সেন্টকে সহায়তা করতে পারে:

a = db.execute('select * from acquisizioni_motes')
b = a.fetchall()
c = b[0]

# and now, finally...
dict(zip(c.keys(), c.values()))

1
বা, যদি আপনি পছন্দ করেন ..: [ডিক (জিপ (আই.কিজ (), আই.ভালিউস ())) আই ইন বি]
মাইচোট দু: খিত

এটিই কেবলমাত্র সিনট্যাক্সের সন্ধান পেয়েছি যা আসলে কাজ করে! আমি এক ঘন্টা ধরে স্টাফ চেষ্টা করছি
স্ল্যাশডটটিয়ার

মূল নির্বাচনের জন্য, RowProxy( cএই উত্তরে) ম্যাপিং প্রোটোকলটি মেনে চলেন, যাতে আপনি কেবল কল করতে পারেন dict(c)
20:56

4

আপনি স্কেলচেমি অবজেক্টকে এর মতো অভিধানে রূপান্তর করতে এবং এটিকে জসন / অভিধান হিসাবে ফিরিয়ে দিতে পারেন।

সহায়ক কার্যাদি:

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) 

ড্রাইভারের কাজ:

def all_products():
    all_products = Products.query.all()
    return to_array(all_products)

3

দুইটি রাস্তা:

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())

3

দস্তাবেজগুলি একটি খুব সাধারণ সমাধান সরবরাহ করে: 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

এলিক্সির এটি কীভাবে করে তা এখানে। এই সমাধানটির মান হ'ল এটি সম্পর্কের অভিধান উপস্থাপনা সহ পুনরাবৃত্তভাবে মঞ্জুরি দেয়।

def to_dict(self, deep={}, exclude=[]):
    """Generate a JSON-style nested dict/list structure from an object."""
    col_prop_names = [p.key for p in self.mapper.iterate_properties \
                                  if isinstance(p, ColumnProperty)]
    data = dict([(name, getattr(self, name))
                 for name in col_prop_names if name not in exclude])
    for rname, rdeep in deep.iteritems():
        dbdata = getattr(self, rname)
        #FIXME: use attribute names (ie coltoprop) instead of column names
        fks = self.mapper.get_property(rname).remote_side
        exclude = [c.name for c in fks]
        if dbdata is None:
            data[rname] = None
        elif isinstance(dbdata, list):
            data[rname] = [o.to_dict(rdeep, exclude) for o in dbdata]
        else:
            data[rname] = dbdata.to_dict(rdeep, exclude)
    return data

লিঙ্কটি মারা গেছে। পরবর্তী সময় দয়া করে এখানেও প্রাসঙ্গিক কোডটি অনুলিপি করুন।
গাস ই

পরের বার করবে। যদি আমি সঠিকভাবে মনে রাখি তবে ফাংশনটি বেশ দীর্ঘ ছিল।
আর্জেণ্টপিপার

2

এই কোডটি দিয়ে আপনি আপনার ক্যোয়ারীতে "ফিল্টার" বা "যোগদান" এবং এই কাজটি যুক্ত করতে পারেন!

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]

1
class User(object):
    def to_dict(self):
        return dict([(k, getattr(self, k)) for k in self.__dict__.keys() if not k.startswith("_")])

এটা কাজ করা উচিত।


1
কলামের নাম "_" দিয়ে শুরু হলে কী হবে?
অনুরাগ ইউনিয়াল

4
আমি কল্পনা করব যে আপনার কলামগুলির একটি শীর্ষস্থানীয় আন্ডারস্কোর দিয়ে সত্যই নামকরণ করা উচিত নয়। আপনি যদি করেন, এটি কাজ করবে না। এটি যদি কেবল বিজোড় হয় তবে আপনি যা জানেন এটি আপনি এই কলামগুলি যুক্ত করতে এটি পরিবর্তন করতে পারেন।
Singletoned

1

মার্কো মারিয়ানির উত্তরে আমার একটি ভিন্নতা রয়েছে, এটি ডেকরেটার হিসাবে প্রকাশিত। মূল পার্থক্য হ'ল এটি সত্ত্বার তালিকা পরিচালনা করবে , পাশাপাশি নিরাপদে কিছু অন্যান্য প্রকারের মানগুলি উপেক্ষা করবে (যা মক ব্যবহার করে পরীক্ষা লেখার সময় খুব কার্যকর):

@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

@ অনুরাগ ইউনিিয়ালের উত্তর সম্পূর্ণ করতে, এখানে একটি পদ্ধতি যা পুনরাবৃত্তভাবে সম্পর্কগুলি অনুসরণ করবে:

from sqlalchemy.inspection import inspect

def to_dict(obj, with_relationships=True):
    d = {}
    for column in obj.__table__.columns:
        if with_relationships and len(column.foreign_keys) > 0:
             # Skip foreign keys
            continue
        d[column.name] = getattr(obj, column.name)

    if with_relationships:
        for relationship in inspect(type(obj)).relationships:
            val = getattr(obj, relationship.key)
            d[relationship.key] = to_dict(val) if val else None
    return d

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    first_name = Column(TEXT)
    address_id = Column(Integer, ForeignKey('addresses.id')
    address = relationship('Address')

class Address(Base):
    __tablename__ = 'addresses'
    id = Column(Integer, primary_key=True)
    city = Column(TEXT)


user = User(first_name='Nathan', address=Address(city='Lyon'))
# Add and commit user to session to create ids

to_dict(user)
# {'id': 1, 'first_name': 'Nathan', 'address': {'city': 'Lyon'}}
to_dict(user, with_relationship=False)
# {'id': 1, 'first_name': 'Nathan', 'address_id': 1}

যদি 'উইথ রিলেশনশিপস' এর জন্য ডিফল্টটি মিথ্যাতে পরিবর্তিত হয় তবে পুনরাবৃত্তির কলটিতে এই মানটি আরও ভালভাবে প্রেরণ করুন। অর্থাত: d[relationship.key] = to_dict(val,with_relationships) if val else None
নিকোলাস হ্যামিল্টন

আমি কীভাবে ফলাফলটি অর্জন করতে পারি, যদি আমি ঠিকানা_আইডি কলামের উপর ভিত্তি করে ব্যবহারকারী এবং ঠিকানা সারণিতে যোগদান করতে চাই এবং ব্যবহারকারীর টেবিল থেকে সমস্ত কলাম এবং ঠিকানা সারণী থেকে কেবল আইডি কলামটি আনতে পারি।
সুধাকর

1

পাইথন ৩.৮++ এর সাহায্যে আমরা এটি ডেটাগ্লাস এবং এটির সাথে আগত asdictপদ্ধতি দিয়ে করতে পারি:

from dataclasses import dataclass, asdict

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, String, Integer, create_engine

Base = declarative_base()
engine = create_engine('sqlite:///:memory:', echo=False)


@dataclass
class User(Base):
    __tablename__ = 'users'

    id: int = Column(Integer, primary_key=True)
    name: str = Column(String)
    email = Column(String)

    def __init__(self, name):
        self.name = name
        self.email = 'hello@example.com'


Base.metadata.create_all(engine)

SessionMaker = sessionmaker(bind=engine)
session = SessionMaker()

user1 = User("anurag")
session.add(user1)
session.commit()

query_result = session.query(User).one()  # type: User
print(f'{query_result.id=:}, {query_result.name=:}, {query_result.email=:}')
# query_result.id=1, query_result.name=anurag, query_result.email=hello@example.com

query_result_dict = asdict(query_result)
print(query_result_dict)
# {'id': 1, 'name': 'anurag'}

কীটি হ'ল @dataclassসাজসজ্জারটি ব্যবহার করা এবং প্রতিটি কলামকে তার ধরণের ( লাইনের : strঅংশ name: str = Column(String)) দিয়ে টীকায়িত করা।

এছাড়াও নোট করুন যেহেতু এটি emailটীকাগুলি নয়, এটি এতে অন্তর্ভুক্ত নয় query_result_dict


পাইথন ৩..7-এ আমি "নামেরর: নাম 'এস্যাসিডিক্ট' সংজ্ঞায়িত করা হয়নি"
ডিভনুল

আমার খারাপ! এটি অজগর 3.8 এ যুক্ত একটি ফাংশন। আমার উত্তর স্থির।
toaruScar

তাই অজগর। 3.8 দুর্দান্ত। তবে আপনার কি আসলেই আর ডি পদ্ধতির দরকার নেই? ঘোষিত এবং ডেটাগ্লাস উভয়ই জেনেরিক ডিআইডি পদ্ধতি সরবরাহ করে।
জেফ লফ্লিন

0

আমি একটি নতুন মিন্টেড পাইথন প্রোগ্রামার এবং যুক্ত টেবিলগুলি নিয়ে JSON এ পেতে সমস্যা বোধ করি। উত্তরগুলি থেকে এখানে তথ্য ব্যবহার করে আমি জেএসএন-তে যুক্তিসঙ্গত ফলাফল ফিরিয়ে আনতে একটি ফাংশন তৈরি করেছি যেখানে টেবিলের নামগুলি উপনাম হওয়া এড়ানো বা ক্ষেত্রগুলির সংঘর্ষে অন্তর্ভুক্ত রয়েছে।

কেবল একটি সেশন ক্যোয়ারির ফলাফলটি পাস করুন:

পরীক্ষা = সেশন ()। ক্যোয়ারী (ভিএমআইএনফো, গ্রাহক) .জাইন (গ্রাহক) .অর্ডার_বি (ভিএমআইএনফো.ভিএম_নাম)

json = sqlAl2json (পরীক্ষা)

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

যদি আপনার মডেলগুলির টেবিল কলামটি মাইএসকিএল কলামের সমতুল্য না হয়।

যেমন :

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())

ব্যবহার করা প্রয়োজন:

 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}

আপনি যদি এইভাবে ব্যবহার করেন তবে আপনি modify_Time এবং create_Time উভয়ই নন

{'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}

কারণ ক্লাস অ্যাট্রিবিউটসের নামটি মাইএসকিএলে কলাম স্টোরের সমান নয়


0

এর বিষয়বস্তুগুলি ফিরিয়ে দিন: শ্রেণি: .KeyedTupleঅভিধান হিসাবে

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

প্রত্যেকের এবং নিজের প্রয়োজনে, আমি এখানে এটি কীভাবে ব্যবহার করব:

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
def to_dict(row):
    return {column.name: getattr(row, row.__mapper__.get_property_by_column(column).key) for column in row.__table__.columns}


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

এই ফাংশন সাহায্য করতে পারে। কলামের নামগুলির পরে গুণাবলীর নাম আলাদা হলে সমস্যার সমাধানের জন্য আমি আরও ভাল সমাধান খুঁজে পাচ্ছি না।


0

আপনার প্রকল্পের যে কোনও জায়গায় আপনার এটির প্রয়োজন হবে, আমি @ অনুরাগকে উত্তর দিয়েছি এটি ঠিকঠাক কাজ করেছে। এই মুহুর্ত পর্যন্ত আমি এটি ব্যবহার করে যাচ্ছিলাম তবে এটি আপনার সমস্ত কোডগুলিকে বিঘ্নিত করবে এবং সত্তা পরিবর্তনের সাথে কাজ করবে না।

বরং এটি চেষ্টা করে দেখুন, এসকিউএলএলচেমিতে আপনার বেস কোয়েরি ক্লাসটি উত্তরাধিকারী করুন

from flask_sqlalchemy import SQLAlchemy, BaseQuery


class Query(BaseQuery):
    def as_dict(self):
        context = self._compile_context()
        context.statement.use_labels = False
        columns = [column.name for column in context.statement.columns]

        return list(map(lambda row: dict(zip(columns, row)), self.all()))


db = SQLAlchemy(query_class=Query)

এর পরে আপনি যেখানেই আপনার অবজেক্টকে "as_dict" পদ্ধতিটি নির্ধারণ করবেন সেখানে উপস্থিত থাকবে।


-1

বেশিরভাগ পরিস্থিতিতে, কলামের নাম তাদের জন্য উপযুক্ত। তবে আপনি কোডটি নিম্নরূপ লিখতে পারেন:

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

ক্ষেত্রের নাম "ইমেল" থাকাকালীন কলাম.নাম "ব্যবহারকারী_ইমেল", কলাম.নাম আগের মতো কাজ করতে পারে নি।

sqlalchemy_base_model.py

আমি উত্তর এখানে লিখুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.