various improvements

This commit is contained in:
Edward Betts 2023-09-22 21:00:56 +01:00
parent 6922b1bf11
commit d1a46dd422
11 changed files with 504 additions and 74 deletions

View file

@ -1,9 +1,13 @@
"""Database models."""
import os
import typing
import sqlalchemy
import sqlalchemy.orm.decl_api
from sqlalchemy import func
from sqlalchemy import Index, func, text
from sqlalchemy.dialects import postgresql
from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.orderinglist import ordering_list
@ -131,6 +135,8 @@ class ConferencePerson(Base):
bio = Column(String)
slug = Column(String)
url = Column(String)
affiliation = Column(String)
photo_url = Column(String)
person = relationship("Person", back_populates="conferences_association")
conference = relationship("Conference", back_populates="people_detail")
@ -165,12 +171,30 @@ class Event(TimeStampedModel):
description = Column(String)
event_type = Column(String)
url = Column(String)
cancelled = Column(Boolean)
search_vector = Column(TSVECTOR)
trigger = text(
"""
CREATE TRIGGER event_vector_update BEFORE INSERT OR UPDATE
ON event FOR EACH ROW EXECUTE FUNCTION
tsvector_update_trigger(search_vector, 'pg_catalog.english', title, abstract, description);
"""
)
Index(
"event_search_vector_idx",
search_vector,
postgresql_using="gin",
postgresql_ops={"abstract_search_vector": "gin_trgm_ops"},
)
conference = relationship("Conference", back_populates="events")
people_detail = relationship(
"EventPerson",
order_by="EventPerson.position",
lazy="dynamic",
back_populates="event",
collection_class=ordering_list("position"),
)
@ -198,7 +222,9 @@ class Person(TimeStampedModel):
)
events = association_proxy("events_association", "event")
conferences_association = relationship("ConferencePerson", back_populates="person")
conferences_association = relationship(
"ConferencePerson", lazy="dynamic", back_populates="person"
)
conferences = association_proxy("conferences_association", "conference")
@property
@ -239,6 +265,39 @@ class Person(TimeStampedModel):
return q
def bio_source(self) -> ConferencePerson | None:
bio_list = [cp for cp in self.conferences_association if cp.bio]
if not bio_list:
return None
if len(bio_list) == 1:
return typing.cast(ConferencePerson, bio_list[0])
recent = max(bio_list, key=lambda cp: cp.conference.start)
len_recent_bio = len(recent.bio)
longest = max(bio_list, key=lambda cp: len(cp.bio))
if recent == longest:
return typing.cast(ConferencePerson, recent)
best = longest if len(longest.bio) > len_recent_bio * 2 else recent
return typing.cast(ConferencePerson, best)
def photo_filename(self) -> str | None:
if self.wikidata_photo:
return os.path.join("wikidata_photo", "thumb", self.wikidata_photo[0])
q = self.conferences_association.filter(ConferencePerson.photo_url.isnot(None))
if q.count() == 0:
return None
best = max(q, key=lambda cp: cp.conference.start)
ext = best.photo_url.rpartition(".")[-1]
filename = f"{best.conference_id}_{self.id}.{ext}"
return os.path.join("conference_photo", filename)
# class PersonPhoto(TimeStampedModel):
# """Person photo."""