async def get(self, request, event_id, connection): """Returns an event.""" # Prepare query query = (select([models.event.t]).select_from( models.event.t).where(models.event.t.c.id == event_id)) # Compile query, execute and parse query, params = asyncpgsa.compile_query(query) try: try: row = await connection.fetchrow(query, *params) except PostgresError: raise exceptions.NotFetchedError if not row: raise exceptions.NotFoundError except exceptions.NotFoundError: return response.json(response_wrapper.error("Event not found"), status=404) event = models.event.json_format(models.event.t.parse(row)) # Return the event return response.json(response_wrapper.ok(event))
async def put(self, request, event_id, session_id, tag_id, connection): """Adds tag to event session.""" # Check, is session and tag exists for name, model, id in [("Session", models.session, session_id), ("Tag", models.tag, tag_id)]: try: query = (select([model.t]).select_from( model.t).where(model.t.c.id == id)) query, params = asyncpgsa.compile_query(query) try: row = await connection.fetchrow(query, *params) except PostgresError: raise exceptions.NotFetchedError if not row: raise exceptions.NotFoundError except exceptions.NotFoundError: return response.json( response_wrapper.error(f"{name} not found"), status=404) # If all is ok, add tag to session query = (models.session_tag.t.insert().values(session_id=session_id, tag_id=tag_id)) # Compile query and execute query, params = asyncpgsa.compile_query(query) try: rows = await connection.execute(query, *params) except PostgresError: raise exceptions.NotCreatedError # Return the HTTP 204 return response.text("", content_type="application/json", status=204)
async def post(self, request, event_id, connection): """Creates a new event person.""" # Person form person = request.json # Check, is event exists try: query_event = (select([models.event.t]).select_from( models.event.t).where( models.event.t.c.id == event_id).apply_labels()) query_event, params = asyncpgsa.compile_query(query_event) try: row = await connection.fetchrow(query_event, *params) except PostgresError: raise exceptions.NotFetchedError if not row: raise exceptions.NotFoundError event = models.event.t.parse(row, prefix="events_") except exceptions.NotFoundError: return response.json(response_wrapper.error("Event not found"), status=404) # If event exists, create a transaction # We need to 1) save person, 2) fetch person from a database async with connection.transaction(): try: query = (models.person.t.insert().values( event_id=event["id"], name=person["name"]).returning(models.person.t.c.id)) query, params = asyncpgsa.compile_query(query) id = await connection.fetchval(query, *params) query = (select([models.person.t]).select_from( models.person.t).where( models.person.t.c.id == id).apply_labels()) query, params = asyncpgsa.compile_query(query) try: row = await connection.fetchrow(query, *params) except PostgresError: raise exceptions.NotFetchedError if not row: raise exceptions.NotFoundError person = models.person.json_format( models.person.t.parse(row, prefix="persons_")) except (PostgresError, exceptions.DatabaseError): raise exceptions.NotCreatedError return response.json(response_wrapper.ok(person), status=201)
async def get(self, request, event_id, connection): """Returns a list of event locations.""" # Check, is event exists try: query_event = (select([models.event.t]) .select_from(models.event.t) .where(models.event.t.c.id == event_id) .apply_labels()) query_event, params = asyncpgsa.compile_query(query_event) try: row = await connection.fetchrow(query_event, *params) except PostgresError: raise exceptions.NotFetchedError if not row: raise exceptions.NotFoundError event = models.event.t.parse(row, prefix="events_") except exceptions.NotFoundError: return response.json( response_wrapper.error("Event not found"), status=404) # If event exists, query all locations query = (select([models.location.t]) .select_from(models.location.t) .where(models.location.t.c.event_id == event["id"]) .order_by(models.location.t.c.name.asc()) .order_by(models.location.t.c.id.desc()) .apply_labels()) # Compile query, execute and parse query, params = asyncpgsa.compile_query(query) try: rows = await connection.fetch(query, *params) except PostgresError: raise exceptions.NotFetchedError locations = [ models.location.json_format(models.location.t.parse(row, prefix="locations_")) for row in rows ] # Return the list return response.json(response_wrapper.ok(locations))
async def get(self, request, connection): """Returns a list of platforms.""" # Validate listing try: pivot, limit, direction = \ self.default_listing.validate_from_request(request) except ValueError: return response.json( response_wrapper.error("Listing arguments error"), status=400) # Prepare query query = select([models.platform.t]).select_from(models.platform.t) # Adjust query according to listing options if pivot is not None: try: query_pivot = query.where(models.platform.t.c.id == pivot) query_pivot, params = asyncpgsa.compile_query(query_pivot) try: row = await connection.fetchrow(query_pivot, *params) except PostgresError: raise exceptions.NotFetchedError if not row: raise exceptions.NotFoundError pivot = models.platform.t.parse(row) except exceptions.NotFoundError: return response.json( response_wrapper.error("Pivot platform not found"), status=400) if direction == listing.Direction.BEFORE: query = ( query.where((models.platform.t.c.slug < pivot["slug"]) | ((models.platform.t.c.slug == pivot["slug"]) & (models.platform.t.c.id > pivot["id"])))) elif direction == listing.Direction.AFTER: query = ( query.where((models.platform.t.c.slug > pivot["slug"]) | ((models.platform.t.c.slug == pivot["slug"]) & (models.platform.t.c.id < pivot["id"])))) # Apply sorting and limit if direction == listing.Direction.BEFORE: query = (query.order_by(models.platform.t.c.slug.desc()).order_by( models.platform.t.c.id.asc()).limit(limit)) elif direction == listing.Direction.AFTER: query = (query.order_by(models.platform.t.c.slug.asc()).order_by( models.platform.t.c.id.desc()).limit(limit)) # Compile query, execute and parse query, params = asyncpgsa.compile_query(query) try: rows = await connection.fetch(query, *params) except PostgresError: raise exceptions.NotFetchedError platforms = [ models.platform.json_format(models.platform.t.parse(row)) for row in rows ] if direction == listing.Direction.BEFORE: platforms.reverse() # Return the list return response.json(response_wrapper.ok(platforms))
async def get(self, request, event_id, connection): """Returns a list of event sessions aka schedule. This endpoint returns complete list, w/o support of listing. """ # Check, is event exists try: query_event = (select([models.event.t]).select_from( models.event.t).where( models.event.t.c.id == event_id).apply_labels()) query_event, params = asyncpgsa.compile_query(query_event) try: row = await connection.fetchrow(query_event, *params) except PostgresError: raise exceptions.NotFetchedError if not row: raise exceptions.NotFoundError event = models.event.t.parse(row, prefix="events_") except exceptions.NotFoundError: return response.json(response_wrapper.error("Event not found"), status=404) # If event exists, query all sessions query = (select([models.session.t]).select_from( models.session.t).where( models.session.t.c.event_id == event["id"]).order_by( models.session.t.c.start_time.asc()).order_by( models.session.t.c.end_time.asc()).order_by( models.session.t.c.created_at.asc()).order_by( models.session.t.c.id.desc()).apply_labels()) # Compile query, execute and parse query, params = asyncpgsa.compile_query(query) try: rows = await connection.fetch(query, *params) except PostgresError: raise exceptions.NotFetchedError sessions = [ models.session.json_format( models.session.t.parse(row, prefix="sessions_")) for row in rows ] # Construct sessions map for fetching persons, locations and tags smap = {session["id"]: session for session in sessions} sids = list(smap.keys()) # Query all persons, locations and tags ids for sessions # TODO: Optimizations for name, field, model in [ ("persons", "person_id", models.session_person), ("locations", "location_id", models.session_location), ("tags", "tag_id", models.session_tag) ]: for session in sessions: session[name] = [] query = (select([model.t]).select_from(model.t).where( model.t.c.session_id.in_(sids))) # Probably, hot spot query, params = asyncpgsa.compile_query(query) try: rows = await connection.fetch(query, *params) except PostgresError: raise exceptions.NotFetchedError rows = [model.t.parse(row) for row in rows] for row in rows: smap[str(row["session_id"])][name].append(str(row[field])) # Return the list return response.json(response_wrapper.ok(sessions))