2016-06-01 23 views
0

Ich arbeite an einigen Wxpython-Widgets, die SQLalchemy, CRUD-Zeug integrieren. Ich habe eine wx.ComboBox, die die Zeilen einer Tabelle auflistet, die durch eine Beziehung verknüpft sind.Abrufen von Spalte aus einer SQLalchemy-Beziehung

class User(Base): 
    __tablename__ = 'user' 
    id = Column(Integer, primary_key=True) 
    name = Column(String(250), nullable=False) 

class Category(Base): 
    __tablename__ = 'category' 
    id = Column(Integer, primary_key=True) 
    name = Column(String(250), nullable=False) 

class Thing(Base): 
    __tablename__ = 'thing' 
    id = Column(Integer, primary_key=True) 
    description = Column(String(500), nullable=False) 
    user_id = Column(Integer, ForeignKey('user.id'), nullable=True) 
    user = relationship(User, foreign_keys = [user_id]) 
    category_id = Column(Integer, ForeignKey('category.id'), nullable=True) 
    category = relationship(Category, foreign_keys = [category_id]) 


class RelationBox(wx.ComboBox): 
    def __init__(self, parent, column): 
     wx.ComboBox.__init__(self, parent, style = wx.CB_READONLY) 
     self.nullable = True # column.nullable 
     self.linked_table = column.mapper.class_ 

     if self.nullable: 
      self.SetItems([""]) 

     self.options = session.query(self.linked_table) 

     session.commit() 

     for option in self.options: 
      self.Append(option.__repr__(), option) 

Ich habe den Code vereinfacht und nur etwas davon extrahiert, um Ihnen hoffentlich ein klareres Bild zu geben. Ich habe es wie folgt umgesetzt:

categories = ["user", "category"] 
category_sizer = wx.BoxSizer(wx.HORIZONTAL) 
self.column_widgets = {} 

for category in categories: 
    box = wx.BoxSizer(wx.VERTICAL) 
    box.Add(wx.StaticText(self, -1, category.capitalize()), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 
    self.column_widgets[category] = RelationBox(self, getattr(Thing, category)) 
    box.Add(self.column_widgets[category], 1, wx.ALIGN_CENTRE|wx.ALIGN_TOP|wx.ALL, 2) 
    category_sizer.Add(box, 0, wx.ALIGN_CENTRE|wx.ALL, 5) 

Ich mag die Säule erhalten, die auf die Beziehung verknüpft ist, damit ich festgelegt, ob das Widget eine leere Option hat oder nicht.

Antwort

1

Sie können die Spalte mit einer Beziehung, die durch Inspektion des .prop Attribut zugeordnet bekommen:

>>> Thing.category.prop.local_columns 
set([Column('category_id', Integer(), ForeignKey('category.id'), table=<thing>)]) 
>>> Thing.category.prop.remote_side 
set([Column('id', Integer(), table=<category>, primary_key=True, nullable=False)])) 

Da es zwei Seiten zu einem Fremdschlüssel sind, müssen Sie vorsichtig, die man sein (local_columns oder remote_side) Sie wählen .

Um dann den Wert von einer Instanz zu holen, gehen Sie wie folgt vor:

col, = Thing.category.prop.local_columns 
key = Thing.__mapper__.get_property_by_column(col).key 
getattr(thing, key) 
Verwandte Themen