【问题标题】:How to loop through relationship tables with SQLAlchemy?如何使用 SQLAlchemy 遍历关系表?
【发布时间】:2020-06-02 14:40:39
【问题描述】:

我正在学习 Flask,我想创建一个数据库,其中包含 3 个相互关联的表:

  1. 公司:关于我工作的公司的信息(编造:))
  2. 工作:关于我在每家公司担任的角色的信息
  3. 任务:关于我在每家公司的每项工作中的任务信息。

代码如下:

from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///work_experience.db'
db = SQLAlchemy(app)

class Company(db.Model):
    id   = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    start_date = db.Column(db.DateTime, nullable=False)
    end_date   =  db.Column(db.DateTime, nullable=False, default=None)
    location   = db.Column(db.String(20), nullable=False, default='N/A')
    jobs = db.relationship('Job', backref='company_')

class Job(db.Model):
    id   = db.Column(db.Integer, primary_key=True)
    position = db.Column(db.String(100), nullable=False)
    start_date = db.Column(db.DateTime, nullable=False)
    end_date   =  db.Column(db.DateTime, nullable=False)
    company_id = db.Column(db.Integer, db.ForeignKey('company.id'))
    tasks = db.relationship('Task', backref='job_')

class Task(db.Model):
    id   = db.Column(db.Integer, primary_key=True)
    description = db.Column(db.String(100), nullable=False)
    start_date = db.Column(db.DateTime, nullable=False)
    end_date   =  db.Column(db.DateTime, nullable=False)
    job_id = db.Column(db.Integer, db.ForeignKey('job.id'))

db.create_all()

我的想法是有一个 for 循环(最终我会用 Jinja2 编写,但现在 python 代码很好),这样我就可以为每家公司打印我的工作以及我完成的任务. 当然,我可以将所有数据放在一张表中,但我正在努力学习。

因此输出应该是这样的:

for company in Companies:
    for job in Jobs:
        for Task in Tasks:
            print(company, job, task)

你能建议我一种聪明而优雅的方式来实现我的目标吗?提前致谢。

【问题讨论】:

  • 您可以在类中添加一个静态变量,该变量将是一个列表。每次调用构造函数时,您都可以在__init__ 函数中执行类似COMPANIES.append(self) 的操作。如果您想使用数据库,那么您应该执行Company.query.all() 之类的操作,它将返回您数据库中所有公司的列表。
  • @geoph9 您好,感谢您的评论!请问您能建议使用第二种方法的回答吗?
  • 通常的方法是根本不使用嵌套的for循环,而是让数据库产生你需要的数据:stackoverflow.com/questions/6044309/…。这在 SQL 中称为 JOIN,它通过组合 2 个表(在某些条件下)生成一个新表。然后,您可以再次加入新表,生成另一个表。当然,数据库系统实际上并没有真正做到这一点,但通常你不需要关心。

标签: python database flask sqlalchemy flask-sqlalchemy


【解决方案1】:

如果我理解正确,您需要一份所有公司、工作、任务的列表。你可以通过查询你的数据库来获得这些(假设你已经插入了一些元组):

for c in Company.query.all():
    print(c.name)
    for r in c.roles:
        print('\t',r.position)
        for t in r.tasks:
            print('\t\t',t.description)

【讨论】:

  • 非常感谢!!我想我成功了!顺便说一句,您能否详细说明 repr 的用法?我为每个类添加了以下代码行: def __repr__(self): return self._repr(id = self.id, position = self.position, start_date = self.start_date, end_date = self.end_date, company_id = self .company_id,任务 = self.tasks)。但我不确定下一步该做什么......那我该如何访问这些值?
  • __repr__ 在 Java 中类似于 toString()。例如def __repr__(self): 的内容可以是:return "ID: {}, name: {}, start_date: {}, end_date: {}, location: {}, jobs: {}".format(self.id, self.name, self.start_date, self.end_date, self.location, self.jobs)。因此,每当您执行print(company) 时,输出将是ID: 1, name: Test, ...
  • 请注意,这会产生笛卡尔积公司×工作×任务,因此所有工作都与所有公司联合,所有任务与所有工作联合,这可能不是“对于每个公司的工作我有什么以及我完成了什么任务”,除非你在 1 家公司中只有 1 份工作,或者在所有公司中都有所有工作等等。单个 SQL 查询(而不是 3 个)可以为您提供正确的结果。阅读如何使用 JOIN
  • @IljaEverilä 感谢您的评论!嗯......我实际上尝试了每个工作和公司的任意数量的任务,它似乎对我来说工作正常: for c in Company.query.all(): print(c.name) for r in c.roles: print('\t',r.position) for t in r.tasks: print('\t\t',t.description)
  • @geoph9 如果您有兴趣,我发布了一个后续问题:stackoverflow.com/questions/62172093/… :)
猜你喜欢
  • 1970-01-01
  • 2019-11-16
  • 2013-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-21
相关资源
最近更新 更多