用sqlalchemy查询联接表

时间:2019-08-13 13:30:04

标签: python sqlalchemy

我有两个表,一个用于参考,另一个用于薪水。我已经在postgres CLI和flask应用程序中成功地将两个表连接在一起,但是尝试在sqlalchemy中查询数据时遇到了问题。

我已经在我的psql CLI上尝试了查询,并且工作正常!

SELECT date, name, profession, wage FROM test2_table JOIN salary ON salary.test2_id = test2_table.id WHERE profession = 'media';

我想我的主要问题是如何在sqlalchemy中做到这一点?

数据库类

class Test_db_02(Base):
    __tablename__ = 'test2_table'
    id = Column('id', Integer, primary_key=True)
    date = Column('date', String(10))
    age = Column('age', Integer)
    profession = Column('profession', String(60))
    city = Column('city', String(60))
    country = Column('country', String(60))

    def __init__(self, date, name, age, profession, city, country):
        self.date = date
        self.name = name
        self.age = age
        self.profession = profession
        self.city = city
        self.country = country

class Salary(Base):
    __tablename__ = 'salary'
    id = Column('id', Integer, primary_key=True)
    wage = Column('wage', String(20))
    test2_id = Column('test2_id', Integer, ForeignKey('test2_table.id')
    wages = relationship("Test_db_02", backref="salary", primaryjoin="Test_db_02.id == Salary.test2_id")

我在python中的查询

@app.route('/reports', methods=['GET', 'POST'])
def reports():
    if request.method == 'GET':
        return render_template('reports.html')
    else:
        if request.form.get("report_options) == "media_prof":
            db_entry = session.query(Test_db_02).join(Test_db_02.salary).filter(Test_db_02.profession=='media')
        media_prof = db_entry.all()
        return render_template('reports.html', media_prof=media_prof)
report.html中的

jinja模板:

{% if media_prof %}
    <h2>Media Freelance Reports</h2>
        <tr>
            <th>ID</th>
            <th>NAME</th>
            <th>PROFESSION</th>
            <th>SALARY</th>
        </tr>
    {% for d in media_prof %}
        <tr>
            <th>{{ d.id }}</th>
            <th>{{ d.name }}</th>
            <th>{{ d.profession }}</th>
            <th>{{ d.salary }}</th>
        </tr>
    {% endfor %}
{% endif %}

幸运的是,它不会使我的Web应用程序崩溃,但没有为每个媒体自由职业者提供薪水,我得到了: [<__main__.Salary object at 0x00CF11B0>]

我觉得这一定是我在python应用程序中查询数据库的方式,或者是我在Jinja中调用变量的方式。

1 个答案:

答案 0 :(得分:1)

由于您是在ORM模式下使用SQLAlchemy(而不是core模式),因此查询的结果

db_entry = session.query(Test_db_02).join(Test_db_02.salary).filter(Test_db_02.profession=='media')
media_prof = db_entry.all()

是Test_db_02实例的列表,每个具有.salary属性的实例都是Salary实例。因此,当您在jinja模板中使用它时,这是正常的:

{% for d in media_prof %}
    <tr>
        <th>{{ d.id }}</th>
        <th>{{ d.name }}</th>
        <th>{{ d.profession }}</th>
        <th>{{ d.salary }}</th>
    </tr>
{% endfor %}

由于d.salarySalary实例的实际列表(由于您的backref和您之间存在一对多的关系),这意味着您可以访问的属性每个薪水对象,例如:.id.wage 例如:

{% for d in media_prof %}
    <tr>
        <th>{{ d.id }}</th>
        <th>{{ d.name }}</th>
        <th>{{ d.profession }}</th>
        {% for s in media_prof.salary %}
            <th>{{ s.id }}</th>
            <th>{{ s.wage }}</th>
        {% endfor %}
    </tr>
{% endfor %}

注意:考虑将您的backref“薪水”重命名为“薪水”,以使其更加明确

编辑: 请注意,对模板外部的内容进行故障排除更容易。从终端,我可以使用以下简化的情况获得正确的输出:

# Load an object in the db with 2 salaries attached to it
t = Test_db_02(city='NY')
s1 = Salary(wage='crazy rich', test2_id=t)
s2 = Salary(wage='mega rich', test2_id=t)
t.salaries = [s1, s2]

session = Session()
session.add(t)
session.commit()

# query & print
session2 = Session()
for test in session2.query(Test_db_02).all():
    print(test.id, test.city)
    for salary in test.salaries:
        print(salary.id, salary.wage)

可打印

1 NY
1 crazy rich
2 mega rich