【发布时间】:2012-04-17 06:26:43
【问题描述】:
我对 SQL 很陌生,对SQL Alchemy 完全陌生,但有一个即将使用这两种方法的项目。所以我想我写一些东西来让自己舒服。由于宿醉,我决定写一些东西来记录酒精含量。
我有 events,其中 users 参与并消费 drinks。这些是我的三个基本表(有一个帮助表 guestlist,用于 users 和 events 之间的 m:n 关系)。
drinks 始终列出所有活动 中所有用户 可用的饮品(无需映射任何内容)。 用户是不时创建的,事件也是如此。所有用户都可以加入所有事件,所以我使用guestlist 表来映射这些。
现在回到问题的核心:我需要跟踪哪个用户在哪个时间喝了哪个饮料。我尝试用另一个表shots(见下文)解决这个问题,但我不确定这是否是一个好的解决方案。
(来源:anyimg.com)
在SQL Alchemy 中,它可能看起来有点像这样(或者不是,但这是我迄今为止想出的)::
guestlist_table = Table('guestlist', Base.metadata,
Column('event_id', Integer, ForeignKey('events.id')),
Column('user_id', Integer, ForeignKey('users.id'))
)
class Event(Base):
__tablename__ = 'events'
id = Column(Integer, primary_key=True)
name = Column(String(80), nullable=False)
started = Column(DateTime, nullable=False, index=True,
default=datetime.datetime.now
)
users = relationship("User", secondary=guestlist_table, backref="events")
# ...
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False, unique=True, index=True)
birthdate = Column(Date, nullable=False)
weight = Column(Integer, nullable=False)
sex = Column(Boolean, nullable=False)
# ...
class Drink(Base):
__tablename__ = 'drinks'
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
volume = Column(Numeric(5,2), nullable=False)
percent = Column(Numeric(5,2), nullable=False)
# ...
class Shots(Base):
__tablename__ = 'shots'
id = Column(Integer, primary_key=True)
at = Column(DateTime, nullable=False,
default=datetime.datetime.now
)
user_id = Column(Integer, ForeignKey('users.id'), index=True)
event_id = Column(Integer, ForeignKey('events.id'), index=True)
drink_id = Column(Integer, ForeignKey('drinks.id'))
user = relationship("User", backref="shots")
event = relationship("Event", backref="shots")
drink = relationship("Drink", uselist=False) # one-to-one, no backref needed
我很难找到一种好的方法来构建一个将事件、用户和饮料映射在一起的表格:我应该如何制定relationships,我该如何query呢?
问题是我觉得我忽略了一些东西。 坦率地说,我完全不知道如何查询?
以下是我大部分时间会提出的问题:
- 我至少需要获取事件中消耗的所有镜头(可能按用户排序)
- 有时我还需要特定用户的所有镜头(可能按事件排序)
- 还有很多计算:
- 每个事件的拍摄次数
- 每位用户的拍摄次数
- 用户在活动中击倒的次数
shots 表是管理此问题的好方法吗?
【问题讨论】:
-
您好@Brutus,根据我的观点,您的关系就像 1 个用户可以参加许多活动,而 1 个活动有很多用户(来宾列表)。 1 个活动有很多饮料,1 个饮料可以在许多活动中提供(酒单)。 1 个用户可以喝很多饮料,1 个饮料可以提供给多个用户(guestdrinklist)。这是正确的吗?
-
所有活动都提供所有饮料,所以我想我可能不需要
drinklist。你所谓的guestdrinklist我试图在Shots类中建模。把班级分成两张表会更好吗? -
如果所有活动都提供所有饮品,则无需指定饮品与活动之间的关系。如果您的字段的子集与其他实体相关联,则您必须指定关系,如果所有相关联,则不需要关系。您可以在饮料和用户之间建立关系。
-
我认为 Victor 的回答很好地涵盖了这一切。事实上,查询各种报告应该很容易。如果您需要那些用于报告,我肯定会尝试在查询中执行这些操作,以便您为报告的每个部分获得尽可能少的 SQL 语句。但是,您可能希望将其中一些作为属性(请参阅docs.sqlalchemy.org/en/latest/orm/…)。你的模型很好。不过要添加的一个明确的事情是从
Shots到guestlist表的复合FK(下一条评论)。 -
__table_args__ = ( ForeignKeyConstraint( ["user_id", "event_id"], ["guestlist.user_id", "guestlist.event_id"], name="fk_guestlist", ), )
标签: python sql orm sqlalchemy