Uprava struktury letu a fotky, uprava GPS pozic v DB

This commit is contained in:
Michal Kváček
2023-07-03 13:23:59 +02:00
parent ba5c3b6a49
commit f8245492b9
18 changed files with 277 additions and 77 deletions
-3
View File
@@ -1,12 +1,9 @@
import asyncio
from logging.config import fileConfig
from sqlalchemy import pool
from sqlalchemy.engine import Connection
from sqlalchemy.ext.asyncio import async_engine_from_config
from alembic import context
import os, sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -7,7 +7,6 @@ Create Date: 2023-05-06 20:57:49.053470
"""
from alembic import op
import sqlalchemy as sa
import database.custom_types
# revision identifiers, used by Alembic.
revision = 'de421195d45c'
@@ -22,7 +21,7 @@ def upgrade() -> None:
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('icao_code', sa.String(length=4), nullable=False),
sa.Column('gps_position', database.custom_types.Point(), nullable=True),
sa.Column('gps_position', sa.Integer(), nullable=True),
sa.Column('elevation', sa.Integer(), nullable=True),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
sa.PrimaryKeyConstraint('id')
@@ -94,7 +93,7 @@ def upgrade() -> None:
op.create_table('point_of_interest',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('gps_position', database.custom_types.Point(), nullable=True),
sa.Column('gps_position', sa.Integer(), nullable=True),
sa.Column('type_id', sa.Integer(), nullable=False),
sa.Column('is_public', sa.Boolean(), server_default='0', nullable=False),
sa.Column('created_by_id', sa.Integer(), nullable=False),
@@ -155,7 +154,7 @@ def upgrade() -> None:
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('filename', sa.String(length=128), nullable=False),
sa.Column('description', sa.Text(), nullable=False),
sa.Column('gps_position', database.custom_types.Point(), nullable=True),
sa.Column('gps_position', sa.Integer(), nullable=True),
sa.Column('flight_id', sa.Integer(), nullable=False),
sa.Column('created_by_id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
@@ -0,0 +1,30 @@
"""flight cover photo
Revision ID: 7304ac2f580b
Revises: 419cf23cbf83
Create Date: 2023-06-29 07:35:54.303608
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '7304ac2f580b'
down_revision = '419cf23cbf83'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('flight', sa.Column('cover_photo_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'flight', 'photo', ['cover_photo_id'], ['id'])
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'flight', type_='foreignkey')
op.drop_column('flight', 'cover_photo_id')
# ### end Alembic commands ###
@@ -0,0 +1,56 @@
"""zmena v gps, pridani poi_id do photo
Revision ID: ef51b2cd596a
Revises: 7304ac2f580b
Create Date: 2023-06-29 08:21:24.755261
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = 'ef51b2cd596a'
down_revision = '7304ac2f580b'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('airport', sa.Column('gps_latitude', sa.Float(), nullable=True))
op.add_column('airport', sa.Column('gps_longitude', sa.Float(), nullable=True))
op.drop_column('airport', 'gps_position')
op.add_column('flight_track', sa.Column('point_of_interest_id', sa.Integer(), nullable=False))
op.drop_constraint('flight_track_ibfk_2', 'flight_track', type_='foreignkey')
op.create_foreign_key(None, 'flight_track', 'point_of_interest', ['point_of_interest_id'], ['id'])
op.drop_column('flight_track', 'poi_id')
op.add_column('photo', sa.Column('gps_latitude', sa.Float(), nullable=True))
op.add_column('photo', sa.Column('gps_longitude', sa.Float(), nullable=True))
op.add_column('photo', sa.Column('poin_of_interest_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'photo', 'point_of_interest', ['poin_of_interest_id'], ['id'])
op.drop_column('photo', 'gps_position')
op.add_column('point_of_interest', sa.Column('gps_latitude', sa.Float(), nullable=True))
op.add_column('point_of_interest', sa.Column('gps_longitude', sa.Float(), nullable=True))
op.drop_column('point_of_interest', 'gps_position')
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('point_of_interest', sa.Column('gps_position', sa.NullType(), nullable=True))
op.drop_column('point_of_interest', 'gps_longitude')
op.drop_column('point_of_interest', 'gps_latitude')
op.add_column('photo', sa.Column('gps_position', sa.NullType(), nullable=True))
op.drop_constraint(None, 'photo', type_='foreignkey')
op.drop_column('photo', 'poin_of_interest_id')
op.drop_column('photo', 'gps_longitude')
op.drop_column('photo', 'gps_latitude')
op.add_column('flight_track', sa.Column('poi_id', mysql.INTEGER(display_width=11), autoincrement=False, nullable=False))
op.drop_constraint(None, 'flight_track', type_='foreignkey')
op.create_foreign_key('flight_track_ibfk_2', 'flight_track', 'point_of_interest', ['poi_id'], ['id'])
op.drop_column('flight_track', 'point_of_interest_id')
op.add_column('airport', sa.Column('gps_position', sa.NullType(), nullable=True))
op.drop_column('airport', 'gps_longitude')
op.drop_column('airport', 'gps_latitude')
# ### end Alembic commands ###
@@ -0,0 +1,34 @@
"""fix typo
Revision ID: 7dc6dd7d0f59
Revises: ef51b2cd596a
Create Date: 2023-06-29 15:43:44.520087
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = '7dc6dd7d0f59'
down_revision = 'ef51b2cd596a'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('photo', sa.Column('point_of_interest_id', sa.Integer(), nullable=True))
op.drop_constraint('photo_ibfk_3', 'photo', type_='foreignkey')
op.create_foreign_key(None, 'photo', 'point_of_interest', ['point_of_interest_id'], ['id'])
op.drop_column('photo', 'poin_of_interest_id')
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('photo', sa.Column('poin_of_interest_id', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True))
op.drop_constraint(None, 'photo', type_='foreignkey')
op.create_foreign_key('photo_ibfk_3', 'photo', 'point_of_interest', ['poin_of_interest_id'], ['id'])
op.drop_column('photo', 'point_of_interest_id')
# ### end Alembic commands ###
@@ -0,0 +1,36 @@
"""uprava cover photo u letu, aircraft.call_sign
Revision ID: f19757a615cc
Revises: 7dc6dd7d0f59
Create Date: 2023-06-29 16:03:51.185228
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = 'f19757a615cc'
down_revision = '7dc6dd7d0f59'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('aircraft', sa.Column('call_sign', sa.String(length=16), nullable=False))
op.drop_column('aircraft', 'name')
op.drop_constraint('flight_ibfk_6', 'flight', type_='foreignkey')
op.drop_column('flight', 'cover_photo_id')
op.add_column('photo', sa.Column('is_flight_cover', sa.Boolean(), server_default='0', nullable=False))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('photo', 'is_flight_cover')
op.add_column('flight', sa.Column('cover_photo_id', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True))
op.create_foreign_key('flight_ibfk_6', 'flight', 'photo', ['cover_photo_id'], ['id'])
op.add_column('aircraft', sa.Column('name', mysql.VARCHAR(length=128), nullable=False))
op.drop_column('aircraft', 'call_sign')
# ### end Alembic commands ###
-13
View File
@@ -1,13 +0,0 @@
from sqlalchemy import func
from sqlalchemy.types import UserDefinedType
class Point(UserDefinedType):
def get_col_spec(self):
return 'POINT'
def bind_expression(self, bindvalue):
return func.ST_GeomFromText(bindvalue, type_=self)
def column_expression(self, col):
return func.ST_AsText(col, type_=self)
+17 -12
View File
@@ -1,9 +1,8 @@
from __future__ import annotations
import datetime
from typing import Set, List
from sqlalchemy import String, DateTime, ForeignKey, Text, Integer, func, Table, Column, Boolean, select
from sqlalchemy import String, DateTime, ForeignKey, Text, Integer, func, Table, Column, Boolean, select, Float
from sqlalchemy.orm import Mapped, relationship, as_declarative, mapped_column
from database.custom_types import Point
from sqlalchemy.ext.asyncio import AsyncSession
@@ -65,7 +64,8 @@ class Airport(BaseModel):
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(128), nullable=False)
icao_code: Mapped[str] = mapped_column(String(4), nullable=False)
gps_position: Mapped[Point] = mapped_column(Point, nullable=True)
gps_latitude: Mapped[float] = mapped_column(Float, nullable=True)
gps_longitude: Mapped[float] = mapped_column(Float, nullable=True)
elevation: Mapped[int] = mapped_column(Integer, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
deleted: Mapped[bool] = mapped_column(Boolean, nullable=False, server_default='0')
@@ -91,7 +91,8 @@ class PointOfInterest(BaseModel):
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(128), nullable=False)
gps_position: Mapped[Point] = mapped_column(Point, nullable=True)
gps_latitude: Mapped[float] = mapped_column(Float, nullable=True)
gps_longitude: Mapped[float] = mapped_column(Float, nullable=True)
type_id: Mapped[int] = mapped_column(Integer, ForeignKey("point_of_interest_type.id"))
is_public: Mapped[bool] = mapped_column(Boolean, server_default='0')
created_by_id: Mapped[int] = mapped_column(Integer, ForeignKey('user.id'))
@@ -108,13 +109,17 @@ class Photo(BaseModel):
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(128), nullable=False)
filename: Mapped[str] = mapped_column(String(128), nullable=False)
is_flight_cover: Mapped[bool] = mapped_column(Boolean, nullable=False, server_default="0")
description: Mapped[str] = mapped_column(Text, nullable=False)
gps_position: Mapped[Point] = mapped_column(Point, nullable=True)
gps_latitude: Mapped[float] = mapped_column(Float, nullable=True)
gps_longitude: Mapped[float] = mapped_column(Float, nullable=True)
point_of_interest_id: Mapped[int] = mapped_column(Integer, ForeignKey("point_of_interest.id"), nullable=True)
flight_id: Mapped[int] = mapped_column(Integer, ForeignKey("flight.id"), nullable=False)
created_by_id: Mapped[int] = mapped_column(Integer, ForeignKey('user.id'))
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
flight: Mapped['Flight'] = relationship()
flight: Mapped['Flight'] = relationship(foreign_keys=[flight_id])
point_of_interest: Mapped['PointOfInterest'] = relationship()
created_by: Mapped['User'] = relationship()
@@ -122,13 +127,13 @@ class Aircraft(BaseModel):
__tablename__ = "aircraft"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(128), nullable=False)
call_sign: Mapped[str] = mapped_column(String(16), nullable=False)
photo_filename: Mapped[str] = mapped_column(String(128), nullable=True)
manufacturer: Mapped[str] = mapped_column(Text, nullable=False, server_default="")
model: Mapped[str] = mapped_column(String(30), nullable=False)
description: Mapped[str] = mapped_column(Text, nullable=False)
model: Mapped[str] = mapped_column(String(30), nullable=False, server_default="")
description: Mapped[str] = mapped_column(Text, nullable=False, server_default="")
organization_id: Mapped[int] = mapped_column(Integer, ForeignKey('organization.id'), nullable=True)
created_by_id: Mapped[int] = mapped_column(Integer, ForeignKey('user.id'))
created_by_id: Mapped[int] = mapped_column(Integer, ForeignKey('user.id'), nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
deleted: Mapped[bool] = mapped_column(Boolean, nullable=False, server_default='0')
@@ -171,7 +176,7 @@ class FlightTrack(BaseModel):
id: Mapped[int] = mapped_column(primary_key=True)
flight_id: Mapped[int] = mapped_column(Integer, ForeignKey("flight.id"), nullable=False)
poi_id: Mapped[int] = mapped_column(Integer, ForeignKey("point_of_interest.id"), nullable=False)
point_of_interest_id: Mapped[int] = mapped_column(Integer, ForeignKey("point_of_interest.id"), nullable=False)
order: Mapped[int] = mapped_column(Integer)
flight: Mapped['Flight'] = relationship()
@@ -205,7 +210,7 @@ class Flight(BaseModel):
landing_airport: Mapped['Airport'] = relationship(foreign_keys=[landing_airport_id])
copilot: Mapped['Copilot'] = relationship(back_populates="flights")
aircraft: Mapped['Aircraft'] = relationship(back_populates="flights")
photos: Mapped[List['Photo']] = relationship()
photos: Mapped[List['Photo']] = relationship(foreign_keys=[Photo.flight_id])
user: Mapped['User'] = relationship(back_populates="flights")
created_by: Mapped['User'] = relationship()
+1 -1
View File
@@ -5,4 +5,4 @@ async def db_session():
async with async_session() as session:
async with session.begin():
yield session
await session.commit()
await session.commit()
-17
View File
@@ -1,17 +0,0 @@
from sqlalchemy import select, desc
from database.models import Flight
from endpoints.base import BaseEndpoint
class FlightsEndpoint(BaseEndpoint):
async def resolve(self):
self.db.add(Flight(name="test"))
await self.db.flush()
data = await self.db.execute(select(Flight).order_by(desc(Flight.id)))
model = data.scalars().first()
return {
"status": model
}
+34
View File
@@ -0,0 +1,34 @@
from collections import defaultdict
from typing import List
from sqlalchemy import select
from strawberry.dataloader import DataLoader
from database import async_session
from database.models import Photo
async def load_collection(ids: List[int]):
async with async_session() as session:
models = (await session.scalars(select(Photo).filter(Photo.flight_id.in_(ids)))).all()
photos_by_flight_id = defaultdict(list)
for photo in models:
photos_by_flight_id[photo.flight_id].append(photo)
return [photos_by_flight_id[id_] for id_ in ids]
async def load(ids: List[int]):
async with async_session() as session:
models = (
await session.scalars(
select(Photo)
.filter(Photo.is_flight_cover.is_(True))
.filter(Photo.flight_id.in_(ids)))
).all()
photos = {p.id: p for p in models}
return [photos.get(id_) for id_ in ids]
photos_dataloader = DataLoader(load_fn=load_collection, cache=False)
cover_photo_loader = DataLoader(load_fn=load)
+2 -6
View File
@@ -1,20 +1,17 @@
import uuid
from typing import List, Optional
import strawberry
from strawberry.file_uploads import Upload
from sqlalchemy import select
from database import models
from graphql_schema.sqlalchemy_to_strawberry_type import strawberry_sqlalchemy_type, strawberry_sqlalchemy_input
from upload_utils import handle_file_upload, delete_file
from upload_utils import handle_file_upload, delete_file, get_public_url
AIRCRAFT_UPLOAD_DEST_PATH = "/app/uploads/aircrafts/"
@strawberry_sqlalchemy_type(models.Aircraft)
class Aircraft:
photo_url: Optional[str] = strawberry.field(
resolver=lambda root: f"http://localhost:8000/uploads/{root.photo_filename}" if root.photo_filename else None
)
photo_url: Optional[str] = strawberry.field(resolver=lambda root: get_public_url(root.photo_filename))
def get_base_query(user_id: int):
@@ -52,7 +49,6 @@ class CreateAircraftMutation:
class CreateAircraftInput:
photo: Optional[Upload]
@strawberry.mutation
async def create_aircraft(root, info, input: CreateAircraftInput) -> Aircraft:
# TODO: kontrola organizace
+13 -5
View File
@@ -2,21 +2,21 @@ from datetime import timedelta
from typing import List, Optional
import strawberry
from sqlalchemy import select
from strawberry.file_uploads import Upload
from database import models
from graphql_schema.dataloaders import copilots_dataloader
from graphql_schema.dataloaders.aircraft import aircraft_dataloader
from graphql_schema.dataloaders.airport import airport_dataloader
from graphql_schema.dataloaders.photos import photos_dataloader, cover_photo_loader
from graphql_schema.entities.aircraft import Aircraft
from graphql_schema.entities.airport import Airport
from graphql_schema.entities.copilot import CopilotType
from graphql_schema.entities.photo import Photo
from graphql_schema.sqlalchemy_to_strawberry_type import strawberry_sqlalchemy_type, strawberry_sqlalchemy_input
from upload_utils import handle_file_upload
# Bude se hodit: https://strawberry.rocks/docs/types/lazy
@strawberry_sqlalchemy_type(models.Flight)
class Flight:
async def load_takeoff_airport(root):
@@ -31,6 +31,12 @@ class Flight:
async def load_copilot(root):
return await copilots_dataloader.load(root.copilot_id)
async def load_photos(root):
return await photos_dataloader.load(root.id)
async def load_cover_photo(root):
return await cover_photo_loader.load(root.id)
def duration_min_calculated(root):
if root.duration_total:
return root.duration_total
@@ -46,6 +52,9 @@ class Flight:
aircraft: Aircraft = strawberry.field(resolver=load_aircraft)
takeoff_airport: Airport = strawberry.field(resolver=load_takeoff_airport)
landing_airport: Airport = strawberry.field(resolver=load_landing_airport)
cover_photo: Optional[Photo] = strawberry.field(resolver=load_cover_photo)
photos: List[Photo] = strawberry.field(resolver=load_photos)
def get_base_query(user_id: int):
@@ -113,7 +122,6 @@ class CreateFlightMutation:
@strawberry.type
class EditFlightMutation:
@strawberry_sqlalchemy_input(models.Flight, exclude_fields=["id"], all_optional=True)
class EditFlightInput:
pass
@@ -122,4 +130,4 @@ class EditFlightMutation:
async def edit_flight(self, info, id: int, input: EditFlightInput) -> Flight:
input_data = input.to_dict()
return await models.Flight.update(info.context.db, id=id, data=input_data)
return await models.Flight.update(info.context.db, id=id, data=input_data)
+37 -8
View File
@@ -1,13 +1,16 @@
from typing import List, Optional
from typing import List
import strawberry
from sqlalchemy import select
from strawberry.file_uploads import Upload
from database import models
from graphql_schema.sqlalchemy_to_strawberry_type import strawberry_sqlalchemy_type, strawberry_sqlalchemy_input
from upload_utils import get_public_url, handle_file_upload
@strawberry_sqlalchemy_type(models.Photo)
class Photo:
pass
url: str = strawberry.field(resolver=lambda root: get_public_url(root.filename))
thumbnail_url: str = strawberry.field(resolver=lambda root: get_public_url(f"thumbs/{root.filename}"))
def get_base_query(user_id: int):
@@ -27,18 +30,37 @@ class PhotoQueries:
@strawberry.type
class DeletePhotoMutation:
class UploadPhotoMutation:
@strawberry_sqlalchemy_input(models.Photo, exclude_fields=["id", "filename"])
class UploadPhotoInput:
photo: Upload
@strawberry.input
class DeletePhotoInput:
id: int
@strawberry.mutation
async def upload_photo(self, info, input: UploadPhotoInput) -> Photo:
photos_dest = f"/app/uploads/photos/{input.flight_id}/"
filename = await handle_file_upload(input.photo, photos_dest)
# todo: udelat nahled do thumbs slozky
created_photo = await models.Photo.create(data={
"flight_id": input.flight_id,
"name": input.name,
"filename": filename,
"description": input.description,
"created_by_id": info.context.user_id,
}, db_session=info.context.db)
return created_photo
@strawberry.type
class EditPhotoMutation:
@strawberry_sqlalchemy_input(models.Photo, exclude_fields=[], all_optional=True)
class UpdatePhotoInput:
class EditPhotoInput:
pass
@strawberry.mutation
async def update_photo(self, info, input: UpdatePhotoInput) -> Photo:
async def update_photo(self, info, input: EditPhotoInput) -> Photo:
query = get_base_query(info.context.user_id)
photo = info.context.db.scalars(query.filter(models.Photo.id == input.id))
@@ -47,6 +69,13 @@ class DeletePhotoMutation:
return photo
@strawberry.type
class DeletePhotoMutation:
@strawberry.input
class DeletePhotoInput:
id: int
@strawberry.mutation
async def delete_photo(self, info, input: DeletePhotoInput) -> Photo:
pass
+4
View File
@@ -1,6 +1,7 @@
from strawberry.tools import merge_types
from graphql_schema.entities.aircraft import CreateAircraftMutation, EditAircraftMutation, DeleteAircraftMutation
from graphql_schema.entities.flight import CreateFlightMutation, EditFlightMutation
from graphql_schema.entities.photo import UploadPhotoMutation, DeletePhotoMutation, EditPhotoMutation
Mutation = merge_types("Mutation", (
CreateAircraftMutation,
@@ -8,4 +9,7 @@ Mutation = merge_types("Mutation", (
DeleteAircraftMutation,
EditFlightMutation,
CreateFlightMutation,
UploadPhotoMutation,
EditPhotoMutation,
DeletePhotoMutation
))
@@ -51,7 +51,11 @@ def strawberry_sqlalchemy_input(
ignored_fields = exclude_fields + ["created_at", "created_by_id", "updated_by_id", "updated_at", "deleted"]
def to_dict(self):
return {name: getattr(self, name) for name, _ in get_columns_from_model(model, ignored_fields) if getattr(self, name) is not None}
return {
name: getattr(self, name)
for name, _ in get_columns_from_model(model, ignored_fields)
if getattr(self, name) is not None
}
def wrapper(cls):
annotations = get_annotations_for_scalars(
@@ -65,10 +69,8 @@ def strawberry_sqlalchemy_input(
for col, col_type in annotations.items():
try:
print("AAAAAAAAAA", col_type)
if col_type._name == 'Optional': # noqa
setattr(cls, col, None)
print(" nastavuji")
except AttributeError:
pass
-5
View File
@@ -8,7 +8,6 @@ from strawberry.fastapi import GraphQLRouter
from config import APP_SECRET_KEY, GRAPHIQL, APP_DEBUG
from dependencies.db import db_session
from endpoints.init_data import InitDataEndpoint
from endpoints.flights import FlightsEndpoint
from endpoints.login import LoginEndpoint, LoginInput, MeEndpoint
from endpoints.registration import RegistrationInput, RegistrationEndpoint
from graphql_schema.schema import schema, GraphQLContext
@@ -119,9 +118,5 @@ class App:
async def init_data(db: AsyncSession = Depends(db_session)):
return await InitDataEndpoint(db).on_get()
@self.api_router.get("/flights", status_code=200)
async def flights(db: AsyncSession = Depends(db_session)):
return await FlightsEndpoint(db).resolve()
# musi byt na konci
app.include_router(self.api_router)
+5
View File
@@ -1,9 +1,14 @@
import os
import uuid
from typing import Optional
from strawberry.file_uploads import Upload
def get_public_url(filename: Optional[str]):
return f"http://localhost:8000/uploads/{filename}" if filename else None
def check_directories(path: str):
if not os.path.isdir(path):
os.makedirs(path)