Как смоделировать отношение "многие ко многим" для трех таблиц в SQLAlchemy (ORM)?

Я ржавый в SQL и совершенно новичок в SQL Alchemy, но у меня есть предстоящий проект, который использует оба. Поэтому я подумал, что напишу что-нибудь, чтобы освоиться. Страдая от похмелья, я решил написать что-нибудь, чтобы следить за уровнем алкоголя.

У меня естьмероприятия , в которыхпользователиучаствуют и потребляютнапитки. Это мои три основные таблицы (с одной вспомогательной таблицей guestlistдля отношения m:n между пользователямии событиями).

drinkсписок напитков, доступных на всех мероприятияхдля всех пользователейпостоянно (не нужно ничего сопоставлять). Время от времени создаются пользователи, а также события.все пользователи могут присоединяться ко всем событиям, поэтому я использую таблицу guestlistдля их сопоставления.

Теперь к сути вопроса:Мне нужно отслеживать, в какое время какой пользователь выпивает, какой напиток при каком событии. Я пытаюсь решить эту проблему с помощью другой таблицы shots(см. ниже), но я не уверен, что это хорошее решение.

ERP Diagram
(источник: 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

Я изо всех сил пытаюсь найти хороший способ построить таблицу, которая сопоставляет события, пользователейи напиткивместе: Как мне сформулировать отношенияи как мне запроситьих?

Дело в том, что мне кажется, что я что-то упустил из виду. И, честно говоря, я совершенно не понимаю, как запроситьего?

Вот запросы, которые я бы делал большую часть времени:

  • Мне как минимум нужно получить все выстрелы, использованные для события (вероятно, отсортированные по пользователю)
  • Иногда мне также нужны все выстрелы для определенного пользователя (вероятно, отсортировано по событию)
  • И много подсчетов:
    • Количество выстрелов на событие
    • Количество выстрелов на пользователя
    • Количество выстрелов, сбитых пользователем во время события

Можно ли использовать таблицу выстреловдля управления этим?

]

7
задан Glorfindel 18 August 2019 в 21:31
поделиться