mirror of
https://github.com/lucaspalomodevelop/eventcally.git
synced 2026-03-13 00:07:22 +00:00
Merge pull request #96 from DanielGrams/issue/95-optimize-loading
Optimize database loading #95
This commit is contained in:
commit
d220867392
@ -13,8 +13,9 @@ from project.api.event_date.schemas import (
|
||||
EventDateListResponseSchema,
|
||||
)
|
||||
from project.models import Event, EventDate
|
||||
from project.services.event import get_events_query
|
||||
from project.services.event import get_events_query, get_event_with_details_or_404
|
||||
from project.services.event_search import EventSearchParams
|
||||
from sqlalchemy.orm import lazyload, load_only
|
||||
|
||||
|
||||
class EventListResource(MethodResource):
|
||||
@ -30,7 +31,7 @@ class EventResource(MethodResource):
|
||||
@doc(summary="Get event", tags=["Events"])
|
||||
@marshal_with(EventSchema)
|
||||
def get(self, id):
|
||||
return Event.query.get_or_404(id)
|
||||
return get_event_with_details_or_404(id)
|
||||
|
||||
|
||||
class EventDatesResource(MethodResource):
|
||||
@ -38,8 +39,13 @@ class EventDatesResource(MethodResource):
|
||||
@use_kwargs(EventDateListRequestSchema, location=("query"))
|
||||
@marshal_with(EventDateListResponseSchema)
|
||||
def get(self, id):
|
||||
event = Event.query.get_or_404(id)
|
||||
return EventDate.query.with_parent(event).paginate()
|
||||
event = Event.query.options(load_only(Event.id)).get_or_404(id)
|
||||
return (
|
||||
EventDate.query.options(lazyload(EventDate.event))
|
||||
.filter(EventDate.event_id == event.id)
|
||||
.order_by(EventDate.start)
|
||||
.paginate()
|
||||
)
|
||||
|
||||
|
||||
class EventSearchResource(MethodResource):
|
||||
|
||||
@ -8,9 +8,10 @@ from project.api.event_date.schemas import (
|
||||
EventDateSearchRequestSchema,
|
||||
EventDateSearchResponseSchema,
|
||||
)
|
||||
from project.models import EventDate
|
||||
from project.models import EventDate, Event
|
||||
from project.services.event import get_event_dates_query
|
||||
from project.services.event_search import EventSearchParams
|
||||
from sqlalchemy.orm import defaultload, lazyload
|
||||
|
||||
|
||||
class EventDateListResource(MethodResource):
|
||||
@ -18,7 +19,7 @@ class EventDateListResource(MethodResource):
|
||||
@use_kwargs(EventDateListRequestSchema, location=("query"))
|
||||
@marshal_with(EventDateListResponseSchema)
|
||||
def get(self, **kwargs):
|
||||
pagination = EventDate.query.paginate()
|
||||
pagination = EventDate.query.options(lazyload(EventDate.event)).paginate()
|
||||
return pagination
|
||||
|
||||
|
||||
@ -26,7 +27,9 @@ class EventDateResource(MethodResource):
|
||||
@doc(summary="Get event date", tags=["Event Dates"])
|
||||
@marshal_with(EventDateSchema)
|
||||
def get(self, id):
|
||||
return EventDate.query.get_or_404(id)
|
||||
return EventDate.query.options(
|
||||
defaultload(EventDate.event).load_only(Event.id, Event.name)
|
||||
).get_or_404(id)
|
||||
|
||||
|
||||
class EventDateSearchResource(MethodResource):
|
||||
|
||||
@ -36,15 +36,32 @@ def _current_user_id_or_none():
|
||||
|
||||
|
||||
class TrackableMixin(object):
|
||||
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
||||
updated_at = Column(
|
||||
DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow
|
||||
)
|
||||
@declared_attr
|
||||
def created_at(cls):
|
||||
return deferred(
|
||||
Column(DateTime, default=datetime.datetime.utcnow), group="trackable"
|
||||
)
|
||||
|
||||
@declared_attr
|
||||
def updated_at(cls):
|
||||
return deferred(
|
||||
Column(
|
||||
DateTime,
|
||||
default=datetime.datetime.utcnow,
|
||||
onupdate=datetime.datetime.utcnow,
|
||||
),
|
||||
group="trackable",
|
||||
)
|
||||
|
||||
@declared_attr
|
||||
def created_by_id(cls):
|
||||
return Column(
|
||||
"created_by_id", ForeignKey("user.id"), default=_current_user_id_or_none
|
||||
return deferred(
|
||||
Column(
|
||||
"created_by_id",
|
||||
ForeignKey("user.id"),
|
||||
default=_current_user_id_or_none,
|
||||
),
|
||||
group="trackable",
|
||||
)
|
||||
|
||||
@declared_attr
|
||||
@ -57,11 +74,14 @@ class TrackableMixin(object):
|
||||
|
||||
@declared_attr
|
||||
def updated_by_id(cls):
|
||||
return Column(
|
||||
"updated_by_id",
|
||||
ForeignKey("user.id"),
|
||||
default=_current_user_id_or_none,
|
||||
onupdate=_current_user_id_or_none,
|
||||
return deferred(
|
||||
Column(
|
||||
"updated_by_id",
|
||||
ForeignKey("user.id"),
|
||||
default=_current_user_id_or_none,
|
||||
onupdate=_current_user_id_or_none,
|
||||
),
|
||||
group="trackable",
|
||||
)
|
||||
|
||||
@declared_attr
|
||||
@ -198,19 +218,19 @@ class AdminUnit(db.Model, TrackableMixin):
|
||||
"EventOrganizer", backref=backref("adminunit", lazy=True)
|
||||
)
|
||||
event_places = relationship("EventPlace", backref=backref("adminunit", lazy=True))
|
||||
location_id = db.Column(db.Integer, db.ForeignKey("location.id"))
|
||||
location_id = deferred(db.Column(db.Integer, db.ForeignKey("location.id")))
|
||||
location = db.relationship("Location")
|
||||
logo_id = db.Column(db.Integer, db.ForeignKey("image.id"))
|
||||
logo_id = deferred(db.Column(db.Integer, db.ForeignKey("image.id")))
|
||||
logo = db.relationship("Image", uselist=False)
|
||||
url = Column(String(255))
|
||||
email = Column(Unicode(255))
|
||||
phone = Column(Unicode(255))
|
||||
fax = Column(Unicode(255))
|
||||
widget_font = Column(Unicode(255))
|
||||
widget_background_color = Column(ColorType)
|
||||
widget_primary_color = Column(ColorType)
|
||||
widget_link_color = Column(ColorType)
|
||||
incoming_reference_requests_allowed = Column(Boolean())
|
||||
url = deferred(Column(String(255)), group="detail")
|
||||
email = deferred(Column(Unicode(255)), group="detail")
|
||||
phone = deferred(Column(Unicode(255)), group="detail")
|
||||
fax = deferred(Column(Unicode(255)), group="detail")
|
||||
widget_font = deferred(Column(Unicode(255)), group="widget")
|
||||
widget_background_color = deferred(Column(ColorType), group="widget")
|
||||
widget_primary_color = deferred(Column(ColorType), group="widget")
|
||||
widget_link_color = deferred(Column(ColorType), group="widget")
|
||||
incoming_reference_requests_allowed = deferred(Column(Boolean()))
|
||||
|
||||
|
||||
@listens_for(AdminUnit, "before_insert")
|
||||
@ -354,13 +374,13 @@ class EventOrganizer(db.Model, TrackableMixin):
|
||||
__table_args__ = (UniqueConstraint("name", "admin_unit_id"),)
|
||||
id = Column(Integer(), primary_key=True)
|
||||
name = Column(Unicode(255), nullable=False)
|
||||
url = Column(String(255))
|
||||
email = Column(Unicode(255))
|
||||
phone = Column(Unicode(255))
|
||||
fax = Column(Unicode(255))
|
||||
location_id = db.Column(db.Integer, db.ForeignKey("location.id"))
|
||||
url = deferred(Column(String(255)), group="detail")
|
||||
email = deferred(Column(Unicode(255)), group="detail")
|
||||
phone = deferred(Column(Unicode(255)), group="detail")
|
||||
fax = deferred(Column(Unicode(255)), group="detail")
|
||||
location_id = deferred(db.Column(db.Integer, db.ForeignKey("location.id")))
|
||||
location = db.relationship("Location")
|
||||
logo_id = db.Column(db.Integer, db.ForeignKey("image.id"))
|
||||
logo_id = deferred(db.Column(db.Integer, db.ForeignKey("image.id")))
|
||||
logo = db.relationship("Image", uselist=False)
|
||||
admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=True)
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ from project.dateutils import (
|
||||
)
|
||||
from sqlalchemy import and_, or_, func
|
||||
from sqlalchemy.sql import extract
|
||||
from sqlalchemy.orm import joinedload, contains_eager
|
||||
from sqlalchemy.orm import joinedload, contains_eager, defaultload
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
|
||||
@ -117,6 +117,83 @@ def get_event_dates_query(params):
|
||||
)
|
||||
|
||||
|
||||
def get_event_date_with_details_or_404(event_id):
|
||||
return (
|
||||
EventDate.query.join(EventDate.event)
|
||||
.join(Event.event_place, isouter=True)
|
||||
.join(EventPlace.location, isouter=True)
|
||||
.options(
|
||||
contains_eager(EventDate.event)
|
||||
.contains_eager(Event.event_place)
|
||||
.contains_eager(EventPlace.location),
|
||||
joinedload(EventDate.event).undefer_group("trackable"),
|
||||
# Place
|
||||
defaultload(EventDate.event)
|
||||
.defaultload(Event.event_place)
|
||||
.joinedload(EventPlace.photo),
|
||||
# Category
|
||||
joinedload(EventDate.event)
|
||||
.joinedload(Event.categories)
|
||||
.load_only(EventCategory.id, EventCategory.name),
|
||||
# Organizer
|
||||
joinedload(EventDate.event)
|
||||
.joinedload(Event.organizer)
|
||||
.undefer_group("detail")
|
||||
.undefer("logo_id")
|
||||
.joinedload(EventOrganizer.logo),
|
||||
# Photo
|
||||
joinedload(EventDate.event).joinedload(Event.photo),
|
||||
# Admin unit
|
||||
joinedload(EventDate.event)
|
||||
.joinedload(Event.admin_unit)
|
||||
.undefer("logo_id")
|
||||
.undefer_group("detail")
|
||||
.undefer_group("widget")
|
||||
.joinedload(AdminUnit.location),
|
||||
# Admin unit logo
|
||||
defaultload(EventDate.event)
|
||||
.defaultload(Event.admin_unit)
|
||||
.joinedload(AdminUnit.logo),
|
||||
)
|
||||
.filter(EventDate.id == event_id)
|
||||
.first_or_404()
|
||||
)
|
||||
|
||||
|
||||
def get_event_with_details_or_404(event_id):
|
||||
return (
|
||||
Event.query.join(EventPlace, isouter=True)
|
||||
.join(Location, isouter=True)
|
||||
.options(
|
||||
contains_eager(Event.event_place).contains_eager(EventPlace.location),
|
||||
defaultload(Event).undefer_group("trackable"),
|
||||
# Place
|
||||
joinedload(Event.event_place).joinedload(EventPlace.photo),
|
||||
# Category
|
||||
joinedload(Event.categories).load_only(
|
||||
EventCategory.id, EventCategory.name
|
||||
),
|
||||
# Organizer
|
||||
joinedload(Event.organizer)
|
||||
.undefer_group("detail")
|
||||
.undefer("logo_id")
|
||||
.joinedload(EventOrganizer.logo),
|
||||
# Photo
|
||||
joinedload(Event.photo),
|
||||
# Admin unit with location
|
||||
joinedload(Event.admin_unit)
|
||||
.undefer("logo_id")
|
||||
.undefer_group("detail")
|
||||
.undefer_group("widget")
|
||||
.joinedload(AdminUnit.location),
|
||||
# Admin unit logo
|
||||
defaultload(Event.admin_unit).joinedload(AdminUnit.logo),
|
||||
)
|
||||
.filter(Event.id == event_id)
|
||||
.first_or_404()
|
||||
)
|
||||
|
||||
|
||||
def get_events_query(params):
|
||||
event_filter = 1 == 1
|
||||
date_filter = EventDate.start >= today
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
from project import db
|
||||
from project.models import EventReviewStatus, EventSuggestion
|
||||
from sqlalchemy import and_
|
||||
from sqlalchemy.orm import load_only
|
||||
|
||||
|
||||
def insert_event_suggestion(event_suggestion):
|
||||
@ -9,7 +10,7 @@ def insert_event_suggestion(event_suggestion):
|
||||
|
||||
|
||||
def get_event_reviews_badge_query(admin_unit):
|
||||
return EventSuggestion.query.filter(
|
||||
return EventSuggestion.query.options(load_only(EventSuggestion.id)).filter(
|
||||
and_(
|
||||
EventSuggestion.admin_unit_id == admin_unit.id,
|
||||
EventSuggestion.review_status == EventReviewStatus.inbox,
|
||||
|
||||
@ -6,6 +6,7 @@ from project.models import (
|
||||
EventReferenceRequestReviewStatus,
|
||||
)
|
||||
from sqlalchemy import and_
|
||||
from sqlalchemy.orm import load_only
|
||||
|
||||
|
||||
def create_event_reference_for_request(request):
|
||||
@ -44,7 +45,9 @@ def get_reference_requests_incoming_query(admin_unit):
|
||||
|
||||
|
||||
def get_reference_requests_incoming_badge_query(admin_unit):
|
||||
return EventReferenceRequest.query.filter(
|
||||
return EventReferenceRequest.query.options(
|
||||
load_only(EventReferenceRequest.id)
|
||||
).filter(
|
||||
and_(
|
||||
EventReferenceRequest.review_status
|
||||
== EventReferenceRequestReviewStatus.inbox,
|
||||
|
||||
@ -35,20 +35,22 @@ from project.services.event import (
|
||||
upsert_event_category,
|
||||
insert_event,
|
||||
update_event,
|
||||
get_event_with_details_or_404,
|
||||
)
|
||||
from project.services.place import get_event_places
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.sql import func, and_
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.orm import lazyload
|
||||
from project.views.event_suggestion import send_event_suggestion_review_status_mail
|
||||
|
||||
|
||||
@app.route("/event/<int:event_id>")
|
||||
def event(event_id):
|
||||
event = Event.query.get_or_404(event_id)
|
||||
user_rights = get_user_rights(event)
|
||||
event = get_event_with_details_or_404(event_id)
|
||||
user_rights = get_menu_user_rights(event)
|
||||
dates = (
|
||||
EventDate.query.with_parent(event)
|
||||
.filter(EventDate.start >= today)
|
||||
EventDate.query.options(lazyload(EventDate.event))
|
||||
.filter(and_(EventDate.event_id == event.id, EventDate.start >= today))
|
||||
.order_by(EventDate.start)
|
||||
.all()
|
||||
)
|
||||
@ -306,6 +308,12 @@ def get_user_rights(event):
|
||||
}
|
||||
|
||||
|
||||
def get_menu_user_rights(event):
|
||||
return {
|
||||
"can_update_event": has_access(event.admin_unit, "event:update"),
|
||||
}
|
||||
|
||||
|
||||
def send_referenced_event_changed_mails(event):
|
||||
# Alle Referenzen
|
||||
references = EventReference.query.filter(EventReference.event_id == event.id).all()
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
from project import app
|
||||
from project.models import EventDate
|
||||
from flask import render_template, url_for, redirect, request
|
||||
from project.views.utils import flash_errors, track_analytics
|
||||
import json
|
||||
from project.jsonld import get_sd_for_event_date, DateTimeEncoder
|
||||
from project.services.event import get_event_date_with_details_or_404
|
||||
from project.services.event_search import EventSearchParams
|
||||
from project.forms.event_date import FindEventDateForm
|
||||
from project.views.event import get_event_category_choices, get_user_rights
|
||||
from project.views.event import get_event_category_choices, get_menu_user_rights
|
||||
|
||||
|
||||
def prepare_event_date_form(form):
|
||||
@ -32,7 +32,7 @@ def event_dates():
|
||||
|
||||
@app.route("/eventdate/<int:id>")
|
||||
def event_date(id):
|
||||
event_date = EventDate.query.get_or_404(id)
|
||||
event_date = get_event_date_with_details_or_404(id)
|
||||
|
||||
if "src" in request.args:
|
||||
track_analytics("event_date", str(id), request.args["src"])
|
||||
@ -45,5 +45,5 @@ def event_date(id):
|
||||
"event_date/read.html",
|
||||
event_date=event_date,
|
||||
structured_data=structured_data,
|
||||
user_rights=get_user_rights(event_date.event),
|
||||
user_rights=get_menu_user_rights(event_date.event),
|
||||
)
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
from project import app, db
|
||||
from project.models import (
|
||||
User,
|
||||
EventDate,
|
||||
AdminUnit,
|
||||
EventOrganizer,
|
||||
EventSuggestion,
|
||||
@ -14,7 +13,10 @@ from flask_security import current_user
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from project.services.event_suggestion import insert_event_suggestion
|
||||
from project.services.event import get_event_dates_query
|
||||
from project.services.event import (
|
||||
get_event_dates_query,
|
||||
get_event_date_with_details_or_404,
|
||||
)
|
||||
from project.services.event_search import EventSearchParams
|
||||
from project.services.place import get_event_places
|
||||
from project.views.utils import (
|
||||
@ -67,7 +69,7 @@ def widget_event_date(au_short_name, id):
|
||||
admin_unit = AdminUnit.query.filter(
|
||||
AdminUnit.short_name == au_short_name
|
||||
).first_or_404()
|
||||
event_date = EventDate.query.get_or_404(id)
|
||||
event_date = get_event_date_with_details_or_404(id)
|
||||
structured_data = json.dumps(
|
||||
get_sd_for_event_date(event_date), indent=2, cls=DateTimeEncoder
|
||||
)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user