2012-04-03 121 views
7

Estoy oxidado en SQL y completamente nuevo en SQL Alchemy, pero tengo un próximo proyecto que usa ambos. Así que pensé en escribir algo para estar cómodo. Sufriendo de una resaca, decidí escribir algo para hacer un seguimiento de los niveles de alcohol.¿Cómo modelo una relación de varios a varios en 3 tablas en SQLAlchemy (ORM)?

que tienen events donde users participar y consumen drinks. Esas son mis tres tablas básicas (con una tabla auxiliar guestlist, para una relación m: n entre usuarios y eventos).

bebidas lista de las bebidas disponibles en todos los eventos a todos los usuarios todo el tiempo (sin necesidad de direccionar nada). usuarios se crean de vez en cuando, por lo que son eventos. todos los usuarios pueden unirse a todos los eventos , entonces uso la tabla guestlist para mapearlos.

Ahora en el corazón de la pregunta: Necesito hacer un seguimiento de a qué hora consume el usuario qué bebida en qué evento. Trato de resolver esto con otra tabla shots (ver a continuación), pero no estoy seguro de si esta es una buena solución.

ERP Diagram http://s1.anyimg.com/img/g6ld1ku/Bildschirmfoto.png

En SQL Alchemy podría parecer algo como esto (o no, pero esto es lo que se me ocurrió hasta ahora) ::

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 

Me esfuerzo por encontrar una buena manera de construir una tabla que asigna eventos, usuarios y bebidas juntos: Cómo debo formular la relationships y cómo hacer yo query es?

La cosa es que siento que he pasado por alto algo. Y, francamente, estoy absolutamente perdido en cómo consulta?

Estas son las preguntas que haría que la mayoría de las veces:

  • yo por lo menos necesito para obtener todos los tiros que se consumen en un caso (probablemente ordenados por el usuario)
  • También a veces necesito todos los tiros para un usuario específico (probablemente ordenado por evento)
  • Y un montón de conteo:
    • Número de disparos por evento
    • Número de disparos por u Ser
    • Número de disparos bebió un usuario en un evento

es la tabla shots una manera aceptable para manejar esto?

+0

Hola @Brutus, según mi opinión, tu relación es como 1 usuario puede participar en muchos eventos y 1 evento tiene muchos usuarios (guestlist). 1 evento tiene muchas bebidas y 1 bebida puede servir en muchos eventos (lista de bebidas). 1 usuario puede tomar muchas bebidas y 1 bebida puede servir a muchos usuarios (guestdrinklist). ¿Es esto correcto? – Nilesh

+0

Todas las bebidas están disponibles en todos los eventos, así que pensé que podría no necesitar 'drinklist'. Lo que llamas 'guestdrinklist' traté de modelar en la clase' Shots'. ¿Sería mejor dividir la clase en dos tablas? – Brutus

+0

Si todas las bebidas están disponibles en todos los eventos, entonces no es necesario especificar la relación entre bebidas y eventos.Debe especificar la relación si el subconjunto de su campo está asociado con otra entidad si todo está asociado, entonces no se necesita relación. Puede crear una relación entre bebidas y usuario. – Nilesh

Respuesta

5

Le sugiero que dibuje un Diagrama de relaciones entre entidades, sería mucho más claro para las personas y usted entender su pregunta.

Para responder a su pregunta:

yo por lo menos necesito para obtener todos los tiros que se consumen en un caso (probablemente ordenados por el usuario)

Para obtener todos los tiros de un evento, se pudo intente

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

El event_id es el id del evento que desea consultar. Para almacenar por el usuario, puede intentar

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

Por supuesto, es posible que desee para ordenar por atributo de un usuario, que puede unirse a la tabla de usuario.

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

bastante fácil.

También a veces necesito todas las vacunas para un usuario específico (probablemente ordenado por evento)

Al igual ejemplo anterior

Número de disparos por evento

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

No las ejecuté, las acabo de escribir aquí, pero deberían funcionar todos si no hiciera un error tipográfico.

+0

Gracias por su respuesta. Lo pruebo tan pronto como llegue a casa. También agregué un ERP. Y sobre el diseño de mi mesa: ¿Crees que la tabla 'shots' es una forma válida de mapear los datos, dados mis consultas-casos? ¿O debería usar otro enfoque para organizar las tablas y las relaciones? – Brutus

Cuestiones relacionadas