স্ক্যালচেমি মডেলের সংজ্ঞায়িত কলামগুলিতে পুনরাবৃত্তি করার পদ্ধতি?


96

আমি কীভাবে একটি এসকিউএএলএলচেমি মডেলের সংজ্ঞায়িত কলামগুলির তালিকার উপরে পুনরাবৃত্তি করব তা বোঝার চেষ্টা করছি। আমি কয়েকটি সিরিয়াল লেখার জন্য এবং মডেলগুলির কয়েকটিতে কপির পদ্ধতিগুলি লেখার জন্য এটি চাই। আমি কেবল পুনরাবৃত্তি করতে পারি না obj.__dict__কারণ এতে প্রচুর এসএ নির্দিষ্ট আইটেম রয়েছে।

নিম্নলিখিত থেকে নাম 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(বৃহত্তর বস্তুর জন্য)।

উত্তর:


84

আপনি নিম্নলিখিত ফাংশনটি ব্যবহার করতে পারেন:

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

এটি এসএ ম্যাজিক বৈশিষ্ট্যগুলি বাদ দেবে, তবে সম্পর্কগুলি বাদ দেবে না। সুতরাং মূলত এটি নির্ভরতা, পিতা-মাতা, বাচ্চাদের ইত্যাদি লোড করতে পারে যা অবশ্যই কাম্য নয়।

তবে এটি আসলে অনেক সহজ কারণ আপনি যদি উত্তরাধিকার সূত্রে উত্তীর্ণ হন তবে আপনার Baseএকটি __table__বৈশিষ্ট্য রয়েছে, যাতে আপনি এটি করতে পারেন:

for c in JobStatus.__table__.columns:
    print c

for c in JobStatus.__table__.foreign_keys:
    print c

SQLAlchemy ম্যাপযুক্ত বস্তু থেকে টেবিলের বৈশিষ্ট্যগুলি কীভাবে আবিষ্কার করবেন তা দেখুন - অনুরূপ প্রশ্ন।

মাইক দ্বারা সম্পাদনা করুন: দয়া করে ম্যাপার.সি এবং ম্যাপার.ম্যাপড_ টেবিলের মতো ফাংশনগুলি দেখুন । যদি 0.8 এবং উচ্চতর ব্যবহার করে থাকেন তবে ম্যাপার.আটার্স এবং সম্পর্কিত ফাংশনগুলিও দেখুন।

ম্যাপার.টটার্সের উদাহরণ :

from sqlalchemy import inspect
mapper = inspect(JobStatus)
for column in mapper.attrs:
    print column.key

21
দ্রষ্টব্য এটি __table__.columnsআপনাকে এসকিউএল ক্ষেত্রের নাম দেবে, আপনি নিজের ওআরএম সংজ্ঞাগুলিতে ব্যবহার করেছেন এমন বৈশিষ্ট্যগুলির নাম নয় (যদি দুটি পৃথক হয়)।
জোশ কেলি

11
আমি পরিবর্তন সুপারিশ পারে '_sa_' != k[:4]থেকে not k.startswith('_sa_')?
মু মাইন্ড

13
পরিদর্শন দিয়ে লুপ করার প্রয়োজন নেই:inspect(JobStatus).columns.keys()
কিরপিত

আপনি model.__dict__[column]স্কেলচেমি দিয়ে মান নির্ধারণ করলে পরিবর্তনগুলি সনাক্ত করতে পারে না।
Sebi2020

63

আপনি ম্যাপার থেকে সংজ্ঞায়িত বৈশিষ্ট্যের তালিকা পেতে পারেন। আপনার ক্ষেত্রে আপনি কেবল কলামপ্রেপার্টি অবজেক্টে আগ্রহী।

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

4
ধন্যবাদ, এটি আমাকে বেসে একটি টডিক্ট পদ্ধতি তৈরি করতে দেয় যা আমি তারপরে একটি ডিকের কাছে একটি উদাহরণ 'ডাম্প' করতে ব্যবহার করি যার পরে আমি পাইলনের জসোনিফাই ডেকরেটার প্রতিক্রিয়াটি পেরিয়ে যেতে পারি। আমি আমার মূল প্রশ্নে কোড উদাহরণ সহ আরও বিশদ নোট রাখার চেষ্টা করেছি তবে এটি জমা দেওয়ার সময় স্ট্যাকওভারফ্লোকে ত্রুটি করে তোলে।
রিক

4
BTW, class_mapperচাহিদা থেকে আমদানি করতে জোরsqlalchemy.orm
priestc

4
যদিও এটি একটি বৈধ উত্তর, সংস্করণ ০.৮ এর পরে এটি ব্যবহার করার পরামর্শ দেওয়া হয়েছে inspect(), যা ঠিক একই ম্যাপার অবজেক্ট হিসাবে প্রত্যাবর্তন করে class_mapper()docs.sqlalchemy.org/en/latest/core/inspection.html
kirpit

4
এটি আমাকে এসকিউএএলএলচেমি মডেলের সম্পত্তির নামগুলি অন্তর্নিহিত কলামের নামগুলিতে মানচিত্র করতে অনেক সহায়তা করেছে।
নির্ভীক ভবিষ্যত

30

আমি বুঝতে পারি যে এটি একটি পুরানো প্রশ্ন, তবে আমি ঠিক একই প্রয়োজনীয়তাটি নিয়ে এসেছি এবং ভবিষ্যতের পাঠকদের জন্য বিকল্প সমাধান দিতে চাই।

জোশ নোট হিসাবে, সম্পূর্ণ এসকিউএল ক্ষেত্রের নামগুলি দ্বারা ফিরে আসবে JobStatus.__table__.columns, সুতরাং আসল ক্ষেত্রের নাম আইডির পরিবর্তে আপনি জবস্ট্যাটাস.আইডি পাবেন । এটি হিসাবে কার্যকর হতে পারে না।

ক্ষেত্রের নামগুলি যেহেতু তারা মূলত সংজ্ঞায়িত হয়েছিল সেগুলির একটি তালিকা পাওয়ার সমাধানটি হ'ল _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._data.keys()যা আপনাকে একটি সুন্দর, পরিষ্কার তালিকা দেয়:

['id', 'desc']

4
সুন্দর! এই পদ্ধতিতে সম্পর্ক স্থাপনেরও কি কোনও উপায় আছে?
কাফন

4
_ডাটা অ্যাটর্নের দরকার নেই, শুধু .. কলামগুলি.কিজ () ট্রিকটি করুন
হুমায়ূন আহমেদ

4
হ্যাঁ, প্রাইভেট _ডাটা অ্যাট্রিবিউটটি ব্যবহার করা যেখানেই সম্ভব এড়ানো উচিত, @ হুমায়ুন আরও সঠিক।
এনজি ওন-ইই

অ্যাট্রিবিউটআরার: __ডেটা

13

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)

12

ধরে নিই যে আপনি এসকিউএএলএলচেমির ঘোষিত ম্যাপিং ব্যবহার করছেন, আপনি __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


এটি সহজ উত্তর।
stgrmks

7

একটি পেতে as_dictআমার ক্লাস সব পদ্ধতি আমি একটি ব্যবহৃত Mixinবর্গ যা কলাকৌশল বর্ণনা ব্যবহার পিঁপড়া 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 রূপ হিসাবে সম্পর্কিত বিষয়গুলির সাথে সম্পর্কিত আমার উদাহরণগুলি রেন্ডার করা দরকার । সুতরাং আমি এখানে এই সামান্য যাদু যোগ করেছি, যা উপরের হিসাবে শ্রেণীর সমস্ত বৈশিষ্ট্য উপর ক্রল হবে এই পার্থক্যের সাথে যে আমি আরও গভীরতর বৈশিষ্ট্যগুলিতে ক্রল করব এবং এগুলির জন্য স্বয়ংক্রিয়ভাবে উত্পন্ন করব ।Relaionshiplinks

দয়া করে মনে রাখবেন যে এটি কেবলমাত্র একক প্রাথমিক কীতে সম্পর্কের জন্য কাজ করবে

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

দয়া করে from sqlalchemy.orm import class_mapper, ColumnPropertyআপনার কোড স্নিপেটের উপরে যুক্ত করুন
জেভিকে

আপনার মন্তব্যের জন্য ধন্যবাদ! আমি অনুপস্থিত আমদানিগুলি যোগ করেছি
ফ্লাজারিনি

এটি স্ক্যালচেমির ঘোষণামূলক বেসটি এখানে আরও পড়ুন ডকস.সকলালচিমি.আর
১৩ /

1
self.__dict__

একটি ডিক প্রদান করে যেখানে কীগুলি বিশিষ্ট নাম এবং বস্তুর মানগুলিকে মান দেয়।

/! \ একটি পরিপূরক বৈশিষ্ট্য রয়েছে: '_ এসএ_স্ট্যান্স_স্টেট' তবে আপনি এটি পরিচালনা করতে পারেন :)


কেবলমাত্র অ্যাট্রিবিউট সেট করা থাকলে।
stgrmks

0

আমি গতিশীলভাবে মডেলের একটি নির্দিষ্ট উদাহরণের ডেটা পেতে চাই। আমি এই কোডটি ব্যবহার করেছি।

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

-1

আমি জানি এটি একটি পুরানো প্রশ্ন, তবে কী সম্পর্কে:

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

আপনি স্ট্রিংতে আইসনস্ট্যান্স (কর্নেল, কলাম) করতে পারবেন না
Muposat

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