Запросы к объединенным таблицам в SQLAlchemy и отображение в ObjectListView - PullRequest
0 голосов
/ 13 февраля 2012

У меня есть ObjectListView, который отображает информацию, полученную из БД SQLite с помощью SQLAlchemy.

def setupOLV(self):
    self.loanResultsOlv.SetEmptyListMsg("No Loan Records Found")
    self.loanResultsOlv.SetColumns([
    ColumnDefn("Date Issued", "left", 100, "date_issued",
                stringConverter="%d-%m-%y"),
    ColumnDefn("Card Number", "left", 100, "card_id"),
    ColumnDefn("Student Number", "left", 100, "person_id"),
    ColumnDefn("Forename", "left", 150, "person_fname"),
    ColumnDefn("Surname", "left", 150, "person_sname"),
    ColumnDefn("Reason", "left", 150, "issue_reason"),
    ColumnDefn("Date Due", "left", 100, "date_due", 
                stringConverter="%d-%m-%y"),
    ColumnDefn("Date Returned", "left", 100, "date_returned", 
                stringConverter="%d-%m-%y")
])

У меня также есть три модели, Кредит:

class Loan(DeclarativeBase):
    """
    Loan model
    """
    __tablename__ = "loans"

    id = Column(Integer, primary_key=True)
    card_id = Column(Unicode, ForeignKey("cards.id"))
    person_id = Column(Unicode, ForeignKey("people.id"))
    date_issued = Column(Date)
    date_due = Column(Date)
    date_returned = Column(Date)
    issue_reason = Column(Unicode(50))
    person = relation("Person", backref="loans", cascade_backrefs=False)
    card = relation("Card", backref="loans", cascade_backrefs=False)

лицо:

class Person(DeclarativeBase):
    """
    Person model
    """
    __tablename__ = "people"

    id = Column(Unicode(50), primary_key=True)
    fname = Column(Unicode(50))
    sname = Column(Unicode(50))

и карта:

class Card(DeclarativeBase):
    """
    Card model
    """
    __tablename__ = "cards"

    id = Column(Unicode(50), primary_key=True)
    active = Column(Boolean)

Я пытаюсь объединить таблицы (loans и people), чтобы получить и отобразить информацию в моем ObjectListView. Вот мой метод запроса:

def getQueriedRecords(session, filterChoice, keyword):
    """
    Searches the database based on the filter chosen and the keyword
    given by the user
    """
    qry = session.query(Loan)
    if filterChoice == "person":
        result = qry.join(Person).filter(Loan.person_id=='%s' % keyword).all()
    elif filterChoice == "card":
        result = qry.join(Person).filter(Loan.card_id=='%s' % keyword).all()
    return result

Я могу получить и отобразить каждое поле, хранящееся в таблице loans, но имя и фамилия (должны быть извлечены из таблицы people и объединены в person.id) не заполнены в моем ObjectListView. У меня есть вывод SQL, поэтому я вижу запрос, и он вообще не выбирается из таблицы people.

Как я могу изменить свой запрос / ObjectListView для получения и отображения этой информации.

ОБНОВЛЕНИЕ: я создал пример сценария, который можно запустить здесь .

Ответы [ 2 ]

1 голос
/ 14 февраля 2012

Вы запрашиваете только заем (qry = session.query (Loan)).Почему вы ожидаете, что в результатах будет что-то еще, кроме того, что в операторе SELECT?

0 голосов
/ 09 ноября 2013

Я признаю, что сам довольно плохо знаком с SQLAlchemy, но подумал, что поделюсь тем, что я использую для отображения результатов моих запросов. У меня есть программа, которая использует базу данных SQLite с 4+ таблицами, и я извлекаю данные из 2-3 из них в одном запросе и отображаю эту информацию в ObjectListView. Я обязан Майку Дрисколлу за его подробные уроки, в частности wxPython и SqlAlchemy: введение в MVC и CRUD .

Вот что я мог бы добавить / изменить в вашем коде.

В разделе вашей модели добавьте класс отображения, например:

def OlvDisplay(object):
    def __init__(self, date_issued, card_id, person_id, fname, sname,
                 issue_reason, date_due, date_returned):
        self.date_issued   = date_issued
        self.card_id       = card_id
        self.person_id     = person_id
        self.person_fname  = fname
        self.person_sname  = sname
        self.issue_reason  = issue_reason
        self.date_due      = date_due
        self.date_returned = date_returned

Этот класс отображения используется в приведенном ниже определении convertResults и помогает убедиться в правильности форматирования данных для ObjectListView.

Корректировка существующей функции запроса:

def getQueriedRecords(session, filterChoice, keyword):
    """
    Searches the database based on the filter chosen and the keyword
    given by the user
    """
    qry = session.query(Loan)
    if filterChoice == "person":
        result = qry.join(Person).filter(Loan.person_id=='%s' % keyword).all()
    elif filterChoice == "card":
        result = qry.join(Person).filter(Loan.card_id=='%s' % keyword).all()
    convertedResults = convertResults(result)
    return convertedResults

То, что мы здесь делаем, - это создание локальной переменной, которая по существу выполняет определение преобразования и сохраняет результаты для следующей строки, которая возвращает эти результаты.

И функция «Преобразователь»:

def convertResults(results):
    finalResults = []
    for record in results:
        result = OlvDisplay(
                        record.date_issued,
                        record.card_id,
                        record.person_id,
                        record.person.fname,
                        record.person.sname,
                        record.issue_reason,
                        record.date_due,
                        record.date_returned
                           )
        finalResults.append(result)
    return finalResults

Важной частью здесь являются 2 строки:

record.person.fname
record.person.sname

Поскольку мы хотим извлечь информацию из другой таблицы, используя установленные отношения, важно обратиться к этим отношениям для фактического просмотра данных.

А для заполнения виджета ObjectListView:

theOutput = getQueriedRecords(session, filterChoice, keyword)
self.setupOLV.SetObjects(theOutput)

Надеюсь, это поможет вам.

-MikeS

...