Как мне моделировать отношение «многие ко многим» для 3 таблиц в SQLAlchemy (ORM)? - PullRequest
7 голосов
/ 03 апреля 2012

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

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

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

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

Диаграмма ERP http://s1.anyimg.com/img/g6ld1ku/Bildschirmfoto.png

В 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

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

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

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

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

Является ли таблица shots хорошим способом справиться с этим?

1 Ответ

5 голосов
/ 04 апреля 2012

Я предлагаю вам нарисовать Диаграмму взаимоотношений сущностей, людям и вам было бы намного понятнее понять ваш вопрос.

Чтобы ответить на ваш вопрос:

I atпо крайней мере, нужно получить все снимки, использованные в событии (вероятно, отсортированные пользователем)

Чтобы получить все снимки события, вы можете попробовать

session.query(Shots).filter_by(event_id=event_id)

Event_id - этоидентификатор события, которое вы хотели бы запросить.Для сохранения по пользователю вы можете попробовать

from sqlalchemy.sql.expression import desc, asc
session.query(Shots) \
    .filter_by(event_id=event_id) \
    .order_by(asc(Shots.user_id))

Конечно, вы можете сортировать по атрибутам пользователя, вы можете присоединиться к таблице пользователей.

from sqlalchemy.sql.expression import desc, asc
session.query(Shots) \
    .filter_by(event_id=event_id) \
    .join(User) \
    .order_by(asc(User.name))

достаточно просто.

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

Как и в предыдущем примере

Количество снимков заevent

session.query(Shots) \
    .filter_by(event_id=event_id) \
    .count()

Я не запускал их, я просто написал их здесь, но они все должны работать, если я не сделаю опечатку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...