使用Pyramid和SQL Alchemy的ORM设计

1 投票
1 回答
1045 浏览
提问于 2025-04-17 18:01

我需要一些帮助来创建我的ORM模型。

我一直在尝试使用Pyramid和SQLAlchemy设计一个网页应用,这是我个人学习的一个经历,同时也是我想为我工作的公司开发的一个小项目。

关于这个应用的一些背景信息(建筑行业)。

这个应用将用作一个投标日程,估算人员可以在上面更新信息;这样前台的秘书就能看到谁在做哪个项目,以及这个项目正在为哪些承包商进行估算。

我已经设计了三个模型,它们看起来是这样的:

class JobListing(Base):
    __tablename__ = 'joblist'
    id = Column(Integer, primary_key=True)
    jobname = Column(String(80), unique=True)
    biddate = Column(DateTime)

    def __init__(self, jobname, biddate):
        self.jobname = jobname
        self.biddate = biddate

class Contractors(Base):
    __tablename__ = 'contractors'
    id = Column(Integer, primary_key=True)
    name = Column(String(80), unique=True)
    address = Column(String(255))
    phone = Column(String(11))
    fax = Column(String(11))

    def __init__(self, name, address, phone, fax):
        self.name = name
        self.address = address
        self.phone = phone
        self.fax = fax

class BiddingList(Base):
    __tablename__ = 'biddinglist'
    id = Column(Integer, primary_key=True)
    job_id = Column(Integer, ForeignKey("joblist.id"))
    job = relationship("JobListing", backref=backref("joblist", order_by=id))
    contractor_id = Column(Integer, ForeignKey("contractors.id"))
    contractors = relationship("Contractors", backref=backref("contractors", order_by=id))

joblisting包含实际的工作信息;工作名称和投标日期就是所需的全部信息。

Contractors包含与实际承包商相关的信息,比如电话、传真等标准信息。

Biddinglist将包含我不太确定该如何组织的信息。我认为这样设计是对的,但它应该只是将承包商与工作ID连接起来。

每个工作中承包商只能列出一次,但一个工作可以有多个承包商。

我的问题是,我这样设计是否正确,还是完全走错了方向?我只是想从一开始就走对路,以便有一个坚实的基础可以继续工作。

1 个回答

0

如果你在对象中不需要存储其他信息,只需要job_idcontractor_id,那么这种情况就叫做多对多关系。SQLAlchemy的文档里有关于如何设置这种关系的例子。简单来说,这种情况下你不需要一个中间的ORM类(虽然你需要一个表),设置好之后,使用起来就像这样:

job = JobListing(jobname="Test Job")
job.contractors.append(joe)
job.contractors.append(bob)
print bob.jobs
> [<JobListing "Test Job">]
bob.jobs.append(another_job)
print bob.jobs
> [<JobListing "Test Job">, <JobListing "Another Job">]

-- 一切都很简单明了。

如果你想在多对多关系中存储一些额外的信息(比如,一个承包商在每个JobListing中可能有不同的role),那么这就叫做关联对象,这是另一种模式。

如果你想限制关系,使得每个承包商只能被添加一次,那我建议你看看如何指定唯一约束

现在你已经知道了所有让它工作的“魔法词”了 :)

还有一点补充说明 - 尽管网上有一些例子,但你并不需要为每个ORM类添加构造函数。SQLAlchemy提供了一个默认的__init__方法,它接受与列名匹配的参数:

class JobListing(Base):
    __tablename__ = 'joblist'
    id = Column(Integer, primary_key=True)
    jobname = Column(String(80), unique=True)
    biddate = Column(DateTime)

obj = JobListing(jobname="Test Job", biddate=datetime.now())

撰写回答