2009-04-23 14 views
15

मेरे पास SQLAlchemy के बारे में प्रश्न है। मैं अपने मैप किए गए वर्ग को शब्दकोश-जैसी विशेषता में कैसे जोड़ सकता हूं, जो स्ट्रिंग कुंजियों को स्ट्रिंग मानों में मैप करता है और जिसे डेटाबेस में संग्रहीत किया जाएगा (उसी मैप ऑब्जेक्ट में मूल मैप ऑब्जेक्ट के रूप में)। मैं चाहता हूं कि यह मेरी वस्तुओं के मनमाना टैग के लिए समर्थन जोड़ें।SQLAlchemy - टैग्स का शब्दकोश

मैं SQLAlchemy दस्तावेज में निम्न उदाहरण पाया:

from sqlalchemy.orm.collections import column_mapped_collection, attribute_mapped_collection, mapped_collection 

mapper(Item, items_table, properties={ 
# key by column 
'notes': relation(Note, collection_class=column_mapped_collection(notes_table.c.keyword)), 
# or named attribute 
'notes2': relation(Note, collection_class=attribute_mapped_collection('keyword')), 
# or any callable 
'notes3': relation(Note, collection_class=mapped_collection(lambda entity: entity.a + entity.b)) 
}) 

item = Item() 
item.notes['color'] = Note('color', 'blue') 

लेकिन मैं निम्नलिखित व्यवहार चाहते हैं:

mapper(Item, items_table, properties={ 
# key by column 
'notes': relation(...), 
}) 

item = Item() 
item.notes['color'] = 'blue' 

यह SQLAlchemy में संभव है?

धन्यवाद

उत्तर

21

सरल उत्तर हाँ है।

बस एक संघ प्रॉक्सी का उपयोग:

from sqlalchemy import Column, Integer, String, Table, create_engine 
from sqlalchemy import orm, MetaData, Column, ForeignKey 
from sqlalchemy.orm import relation, mapper, sessionmaker 
from sqlalchemy.orm.collections import column_mapped_collection 
from sqlalchemy.ext.associationproxy import association_proxy 

एक परीक्षण वातावरण बनाएँ:

tb_items = Table('items', meta, 
     Column('id', Integer, primary_key=True), 
     Column('name', String(20)), 
     Column('description', String(100)), 
    ) 
tb_notes = Table('notes', meta, 
     Column('id_item', Integer, ForeignKey('items.id'), primary_key=True), 
     Column('name', String(20), primary_key=True), 
     Column('value', String(100)), 
    ) 
meta.create_all() 

वर्ग (ध्यान दें कक्षा में association_proxy):

engine = create_engine('sqlite:///:memory:', echo=True) 
meta = MetaData(bind=engine) 

तालिकाओं को परिभाषित करें:

class Note(object): 
    def __init__(self, name, value): 
     self.name = name 
     self.value = value 
class Item(object): 
    def __init__(self, name, description=''): 
     self.name = name 
     self.description = description 
    notes = association_proxy('_notesdict', 'value', creator=Note) 

मैपिंग:

mapper(Note, tb_notes) 
mapper(Item, tb_items, properties={ 
     '_notesdict': relation(Note, 
      collection_class=column_mapped_collection(tb_notes.c.name)), 
    }) 

तो बस यह परीक्षण:

Session = sessionmaker(bind=engine) 
s = Session() 

i = Item('ball', 'A round full ball') 
i.notes['color'] = 'orange' 
i.notes['size'] = 'big' 
i.notes['data'] = 'none' 

s.add(i) 
s.commit() 
print i.notes 

कि प्रिंट:

{u'color': u'orange', u'data': u'none', u'size': u'big'} 

लेकिन, नोट्स तालिका में होते हैं?

>>> print list(tb_notes.select().execute()) 
[(1, u'color', u'orange'), (1, u'data', u'none'), (1, u'size', u'big')] 

यह काम करता है !! :)

+0

आप 'i' को कैसे हटा सकते हैं?मुझे 'एसेज एसेरशनररर' मिलता है ("निर्भरता नियम '% s' '% (r, mapperutil.state_str (dest)) पर प्राथमिक कुंजी कॉलम'% s 'को खाली करने की कोशिश करता है)' s.delete (i) ' – Sardathrion

+0

मेरे अपने प्रश्न का उत्तर दें: 'मैपर में (आइटम [...], कैस्केड =" सब, डिलीट-अनाथ "), [...]' – Sardathrion

-6

सरल उत्तर 'नहीं' है।

SQLAlchemy SQL डेटाबेस पर रैपर है।

आपके द्वारा उद्धृत संबंध उदाहरण एसक्यूएल टेबल के बीच एक रिश्ते का अनुवाद एक पायथन मानचित्र-जैसी संरचना में अनुवाद करने के लिए करते हैं ताकि SQL चयन कथन करने और अन्य तालिका में पंक्तियों का पता लगाने में थोड़ा आसान हो सके।

item.notes['color'] = Note('color', 'blue') 

आवश्यक है क्योंकि Note दो स्तंभों के साथ एक अलग तालिका है। आप Note भाग बाहर नहीं छोड़ सकते हैं।

आपको यह अन्य SQL तालिका परिभाषित करनी होगी, और आपको उस SQL ​​तालिका में मैप किए गए ऑब्जेक्ट्स बनाना होगा।