2010-04-04 9 views
10

मैं निम्नलिखित समस्या है: (: columnValue columnName) मानSQLAlchemy गतिशील मानचित्रण


class Word(object): 

    def __init__(self): 
     self.id = None 
     self.columns = {} 

    def __str__(self): 
     return "(%s, %s)" % (str(self.id), str(self.columns)) 

self.columns एक dict जो आयोजन करेगा है:

मैं कक्षा की है। स्तंभों के नाम कार्यावधि में जाना जाता है और वे एक wordColumns सूची में लोड किए गए हैं, उदाहरण के


wordColumns = ['english', 'korean', 'romanian'] 

wordTable = Table('word', metadata, 
        Column('id', Integer, primary_key = True) 
       ) 
for columnName in wordColumns: 
    wordTable.append_column(Column(columnName, String(255), nullable = False)) 

के लिए मैं भी एक स्पष्ट नक्शाकार गुण "बल" तालिका स्तंभ शब्द पर मैप किया जाने के लिए बनाया। कॉलम [कॉलमनाम], word.columnName के बजाय, मुझे मैपिंग पर कोई त्रुटि नहीं मिलती है, लेकिन ऐसा लगता है कि यह काम नहीं करता है।


mapperProperties = {} 
for column in wordColumns: 
    mapperProperties['columns[\'%']' % column] = wordTable.columns[column] 

mapper(Word, wordTable, mapperProperties) 

जब मैं एक शब्द भी वस्तु लोड, SQLAlchemy एक वस्तु जो word.columns [ 'अंग्रेज़ी'], word.columns [ 'कोरियाई'] आदि लक्षण इसे word.columns में लोड करने के बजाय है dict बनाता है । तो प्रत्येक कॉलम के लिए, यह एक नई संपत्ति बनाता है। इसके अलावा word.columns शब्दकोश भी मौजूद नहीं है।

वैसे ही, जब मैं एक शब्द को जारी रखने का प्रयास करता हूं, तो SQLAlchemy शब्द.columns के बजाय word.columns ['english'] (स्ट्रिंग प्रकार) नामक गुणों में कॉलम मान ढूंढने की अपेक्षा करता है।

मुझे यह कहना है कि पाइथन और स्क्लाक्लेमी के साथ मेरा अनुभव काफी सीमित है, शायद ऐसा करना संभव नहीं है जो मैं करने की कोशिश कर रहा हूं।

किसी भी मदद की सराहना की,

अग्रिम धन्यवाद।

उत्तर

29

ऐसा लगता है कि आप columnsdict का उपयोग करने के बजाय सीधे विशेषताओं का उपयोग कर सकते हैं।

निम्नलिखित सेटअप पर विचार करें:

from sqlalchemy import Table, Column, Integer, Unicode, MetaData, create_engine 
from sqlalchemy.orm import mapper, create_session 

class Word(object): 
    pass 

wordColumns = ['english', 'korean', 'romanian'] 
e = create_engine('sqlite://') 
metadata = MetaData(bind=e) 

t = Table('words', metadata, Column('id', Integer, primary_key=True), 
    *(Column(wordCol, Unicode(255)) for wordCol in wordColumns)) 
metadata.create_all() 
mapper(Word, t) 
session = create_session(bind=e, autocommit=False, autoflush=True) 

कि खाली वर्ग के साथ आप कर सकते हैं:

w = Word() 
w.english = u'name' 
w.korean = u'이름' 
w.romanian = u'nume' 

session.add(w) 
session.commit() 

और जब आप डेटा का उपयोग करना चाहते हैं:

w = session.query(Word).filter_by(english=u'name').one() 
print w.romanian 

कि है पूरे sqlalchemy के ORM बिंदु, उपयोग करने के बजाय डेटा तक पहुंचने के लिए tuple या dict, आप विशेषता-जैसे अपनी कक्षा पर पहुंच का उपयोग करते हैं।

तो मैं dict का उपयोग करने के कारणों के लिए सोच रहा था। शायद ऐसा इसलिए है क्योंकि आपके पास भाषा के नामों के साथ तार हैं। ठीक है, उसके लिए आपको अजगर के getattr और setattr बजाय, के रूप में आप किसी भी अजगर वस्तु पर होगा इस्तेमाल कर सकते हैं:

language = 'korean' 
print getattr(w, language) 

है कि आपके सभी मुद्दों का हल करना चाहिए।


कहा, तब भी आप स्तंभों को dict की तरह उपयोग का उपयोग करना चाहते हैं, यह भी संभव है।आपको बस dict-ऑब्जेक्ट की तरह लागू करना होगा। अब मैं ऐसा करने के लिए कोड प्रदान करूंगा, भले ही मुझे लगता है कि यह बिल्कुल अनावश्यक अव्यवस्था है, क्योंकि विशेषता पहुंच इतनी साफ है। यदि उपरोक्त विधि का उपयोग करके आपकी समस्या पहले ही हल हो चुकी है, तो इस बिंदु के नीचे दिए गए कोड का उपयोग न करें।

आप इसे Word वर्ग पर कर सकता है:

class Word(object): 
    def __getitem__(self, item): 
     return getattr(self, item) 
    def __setitem__(self, item, value): 
     return setattr(self, item, value) 

सेटअप के बाकी के रूप में ऊपर काम करता है। तो फिर तुम इसे इस तरह इस्तेमाल कर सकते हैं:

w = Word() 
w['english'] = u'name' 

आप तो एक columns विशेषता चाहते हैं तो आप के रूप में आप का इरादा एक dict तरह

class AttributeDict(DictMixin): 
    def __init__(self, obj): 
     self._obj = obj 
    def __getitem__(self, item): 
     return getattr(self._obj, item) 
    def __setitem__(self, item, value): 
     return setattr(self._obj, item, value) 

class Word(object): 
    def __init__(self): 
     self.columns = AttributeDict(self) 

तो फिर तुम इस्तेमाल कर सकते हैं की जरूरत है:

w = Word() 
w.columns['english'] = u'name' 

मुझे लगता है कि आप इस बात से सहमत होंगे कि यह कोई अतिरिक्त लाभ के साथ अनावश्यक रूप से जटिल है।

+2

इस तरह के एक पूर्ण उत्तर लिखने के लिए समय लेने के लिए धन्यवाद। मैं मानता हूं कि पहला समाधान दूसरे की तुलना में अधिक स्वच्छ और अधिक सुरुचिपूर्ण है। मेरे पास इस तथ्य को छोड़कर एक नियम का उपयोग करने का कोई अच्छा कारण नहीं था कि यह "सामान्य" चीज थी जो मेरे दिमाग में आई थी। जैसा कि मैंने पहले कहा था, मैं पाइथन में नया हूं और मैंने अभी तक गतिशील भाषाओं के लाभों का लाभ उठाने के लिए सीखा नहीं है। मैं आपके पहले समाधान का उपयोग करूंगा। धन्यवाद फिर से :) –

+3

मैं इस बात पर नहीं जा सकता कि इस तरह की कितनी पोस्ट यहां मौजूद हैं, लेकिन जब भी मैं एक देखता हूं तब भी मैं डरता हूं। इसमें इतना विचार डालने के लिए धन्यवाद। एक साल बाद, नए लोगों के लिए अभी भी सहायक। आपको चेयर – Profane

+0

अब, अगर मैं शब्द शुरू करने के लिए kwargs का उपयोग करना चाहता था, जैसे w = Word (english = 'name', korean = 'Phoo', romanian = 'nume'), यह कैसे काम करेगा? मेरे मामले में यह एक __init__ त्रुटि फेंकने पर जारी रहेगा। धन्यवाद! – Julius

3

मैंने नोस्को के समाधान का उपयोग किया (धन्यवाद!) लेकिन कॉलम लाइन (सीएसवी की पहली पंक्ति) के भीतर मेरे पास पहले से ही एक प्राथमिक कुंजी (पीके_col के रूप में पारित) थी। तो मैंने सोचा कि मैं अपना संशोधन साझा करूंगा। मैंने एक टर्नरी का इस्तेमाल किया।

table = Table(tablename, metadata, 
    *((Column(pk_col, Integer, primary_key=True)) if rowname == pk_col else (Column(rowname, String())) for rowname in row.keys())) 
table.create()