"""Database models.""" import sqlalchemy import sqlalchemy.orm.decl_api from sqlalchemy import func from sqlalchemy.dialects import postgresql from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.orderinglist import ordering_list from sqlalchemy.orm import relationship from sqlalchemy.schema import Column, ForeignKey from sqlalchemy.types import Date, DateTime, Integer, String from .database import session Base: sqlalchemy.orm.decl_api.DeclarativeMeta = declarative_base() Base.query = session.query_property() class TimeStampedModel(Base): """Time stamped model.""" __abstract__ = True created = Column(DateTime, default=func.now()) modified = Column(DateTime, default=func.now(), onupdate=func.now()) class Conference(TimeStampedModel): """Conference.""" __tablename__ = "conference" id = Column(Integer, primary_key=True) title = Column(String, nullable=False) start = Column(Date) end = Column(Date) days = Column(Integer) timezone = Column(String) location = Column(String) country = Column(String) acronym = Column(String) url = Column(String) schedule_xml_url = Column(String) short_name = Column(String, unique=True) venue_id = Column(Integer, ForeignKey("venue.id")) people_detail = relationship( "ConferencePerson", lazy="dynamic", back_populates="conference" ) people = association_proxy("people_detail", "person") events = relationship( "Event", order_by="Event.event_date", back_populates="conference", lazy="dynamic", ) venue = relationship("Venue", back_populates="conferences") class City(TimeStampedModel): """City.""" __tablename__ = "city" id = Column(Integer, primary_key=True) slug = Column(String, nullable=False, unique=True) name = Column(String, nullable=False) country_code = Column(String, ForeignKey("country.alpha2"), nullable=False) wikidata_qid = Column(String, nullable=False) venues = relationship("Venue", back_populates="city") country = relationship("Country", back_populates="cities") class Venue(TimeStampedModel): """Venue.""" __tablename__ = "venue" id = Column(Integer, primary_key=True) name = Column(String, nullable=False) city_id = Column(Integer, ForeignKey("city.id")) wikidata_qid = Column(String, nullable=False) conferences = relationship("Conference", back_populates="venue") city = relationship("City", back_populates="venues") class Country(TimeStampedModel): """Country.""" __tablename__ = "country" alpha2 = Column(String, primary_key=True) name = Column(String) wikidata_qid = Column(String, nullable=False) cities = relationship("City", back_populates="country") class ConferencePerson(Base): __tablename__ = "conference_person" conference_id = Column(Integer, ForeignKey("conference.id"), primary_key=True) person_id = Column(Integer, ForeignKey("person.id"), primary_key=True) named_as = Column(String) bio = Column(String) slug = Column(String) url = Column(String) person = relationship("Person", back_populates="conferences_association") conference = relationship("Conference", back_populates="people_detail") class Event(TimeStampedModel): """Event.""" __tablename__ = "event" id = Column(Integer, primary_key=True) conference_id = Column(Integer, ForeignKey("conference.id"), nullable=False) event_date = Column(DateTime) # day = Column(Integer) guid = Column(String) start = Column(String) duration = Column(String) room = Column(String) track = Column(String) slug = Column(String) title = Column(String, nullable=False) abstract = Column(String) description = Column(String) event_type = Column(String) url = Column(String) conference = relationship("Conference", back_populates="events") people_detail = relationship( "EventPerson", order_by="EventPerson.position", back_populates="event", collection_class=ordering_list("position"), ) people = association_proxy( "people_detail", "person", creator=lambda i: EventPerson(person=i[0], named_as=i[1]), ) class Person(TimeStampedModel): """Person.""" __tablename__ = "person" id = Column(Integer, primary_key=True) name = Column(String) wikidata_qid = Column(String) gender = Column(String) wikidata_photo = Column(postgresql.ARRAY(String)) events_association = relationship( "EventPerson", back_populates="person", lazy="dynamic", ) events = association_proxy("events_association", "event") conferences_association = relationship("ConferencePerson", back_populates="person") conferences = association_proxy("conference_association", "conference") # photos = relationship("PersonPhoto", back_populates="person") def events_by_time(self): q = ( session.query(Event) .join(EventPerson) .filter(EventPerson.person == self) .order_by(Event.event_date.desc()) ) return q # class PersonPhoto(TimeStampedModel): # """Person photo.""" # # __tablename__ = "person_photo" # person_id = Column(Integer, ForeignKey("person.id"), primary_key=True) # source_filename = Column(String) # # person = relationship("Person", back_populates="photos") class EventPerson(Base): """Event person.""" __tablename__ = "event_person" event_id = Column(Integer, ForeignKey("event.id"), primary_key=True) person_id = Column(Integer, ForeignKey("person.id"), primary_key=True) position = Column(Integer, nullable=False) person = relationship("Person", back_populates="events_association") event = relationship("Event", back_populates="people_detail")