使用Pyramid和SQL Alchemy的ORM设计
我需要一些帮助来创建我的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 个回答
如果你在job_id
和contractor_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())