在 SQLAlchemy 中查询连接表并在 ObjectListView 中显示

发布于 2025-01-04 22:05:16 字数 2728 浏览 1 评论 0原文

我有一个 ObjectListView,它显示使用 SQLAlchemy 从 SQLite DB 检索的信息。

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

我还有三个模型,Loan:

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)

Person:

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

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

和 Card:

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

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

我正在尝试连接表(loanspeople),以便检索并显示 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 以检索和显示此信息。 ?

更新:我创建了一个可在此处运行的示例脚本。

I have an ObjectListView that displays information retrieved from an SQLite DB with 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")
])

I also have three models, Loan:

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)

Person:

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

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

and Card:

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

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

I am trying to join the tables (loans and people) in order to retrieve and display the information in my ObjectListView. Here is my query method:

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

I can retrieve and display every field stored in the loans table but forename and surname (should be drawn from people table and joined on person.id) are blank in my ObjectListView. I have SQL output on so I can see the query and it is not selecting at all from the people table.

How can I modify my query/ObjectListView to retrieve and display this information. ?

UPDATE: I have created an example script that is runnable here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吻泪 2025-01-11 22:05:16

您仅查询贷款 (qry = session.query(Loan))。除了 SELECT 语句中的内容之外,为什么您期望结果中包含其他内容?

You're only querying for a Loan (qry = session.query(Loan)). Why do you expect something else to be in the results besides what's in the SELECT statement?

み青杉依旧 2025-01-11 22:05:16

我承认我自己对 SQLAlchemy 还很陌生,但我想我会分享我用来显示查询结果的内容。我有一个程序,它使用带有 4 个以上表的 SQLite DB,我在单个查询中从其中的 2-3 个表中提取数据,并在 ObjectListView 中显示此信息。我欠 Mike Driscoll 深入的教程,特别是 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

这里重要的部分是两行:

record.person.fname
record.person.sname

由于我们希望使用已建立的关系从另一个表中提取信息,因此引用该关系以实际查看数据非常重要。

并填充 ObjectListView 小部件:

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

希望这可以帮助您。

-迈克S

I admit that I am pretty new to SQLAlchemy myself, but I thought I would share what I use to display results from my queries. I have a program that uses a SQLite DB with 4+ tables and I pull data from 2-3 of them in a single query and display this information in an ObjectListView. I owe Mike Driscoll for his in depth tutorials, particularly wxPython and SqlAlchemy: An Intro to MVC and CRUD.

Here is what I would possibly add/change in your code.

In your model section add a "display" class such as:

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

This display class is used in the convertResults definition below and assists with making sure the data is formatted properly for the ObjectListView.

The adjustment to your existing query function:

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

What we're doing here is creating a local variable that is essentially running the conversion definition and storing the results for the next line, which returns those results.

And the "Convertor" function:

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

The important part here are the 2 lines:

record.person.fname
record.person.sname

Since we are wanting to pull information from another table using the established relationship it is important to refer to that relationship to actually see the data.

And to populate the ObjectListView Widget:

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

Hope this helps you out.

-MikeS

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文