Uprava struktury letu a fotky, uprava GPS pozic v DB
This commit is contained in:
@@ -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 ###
|
||||
+36
@@ -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 ###
|
||||
@@ -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
@@ -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,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
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user