Resize obrazku, deploy, bugfixing

This commit is contained in:
Michal Kváček
2023-08-26 11:46:28 +02:00
parent 11866e154c
commit b70223896c
14 changed files with 593 additions and 37 deletions
+13 -8
View File
@@ -1,15 +1,20 @@
import os
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
def create_db_engine(
user: str = "root",
password: str = "",
host: str = "db",
port: int = 3306,
database: str = "ull_tracker",
):
database_url = f'mysql+aiomysql://{user}:{password}@{host}:{port}/{database}?charset=utf8'
def get_database_url():
user = os.environ.get("MYSQL_USER", "root")
password = os.environ.get("MYSQL_PASSWORD", "")
host = os.environ.get("MYSQL_HOST", "db")
port = int(os.environ.get("MYSQL_PORT", 3306))
database = os.environ.get("MYSQL_DATABASE", "ull_tracker")
return f'mysql+aiomysql://{user}:{password}@{host}:{port}/{database}?charset=utf8'
def create_db_engine():
database_url = get_database_url()
return create_async_engine(database_url, future=True, echo=True)
-1
View File
@@ -17,7 +17,6 @@ def authenticated_user_only(raise_when_unauthorized: bool = True, return_value_u
raise HTTPException(HTTP_401_UNAUTHORIZED, "Not authorized")
else:
return return_value_unauthorized
return await func(*args, **kwargs)
return decorator
+1 -1
View File
@@ -5,5 +5,5 @@ async def db_session():
async with async_session() as session:
async with session.begin():
yield session
await session.commit()
await session.flush()
await session.commit()
+15 -6
View File
@@ -1,3 +1,4 @@
import asyncio
from datetime import timedelta
from typing import List, Optional, Annotated, TYPE_CHECKING, Tuple
import strawberry
@@ -161,14 +162,21 @@ class CreateFlightMutation:
@authenticated_user_only()
async def create_flight(self, info, input: CreateFlightInput) -> Flight:
db = info.context.db
aircraft_id = await handle_aircraft_save(db, info.context.user_id, input.aircraft)
data = input.to_dict()
takeoff_airport, landing_airport = await get_airports(db, input.takeoff_airport.id, input.landing_airport.id)
weather_takeoff = await handle_weather_info(db, data['takeoff_datetime'], takeoff_airport)
weather_landing = await handle_weather_info(db, data['landing_datetime'], landing_airport)
return await models.Flight.create(db, data={
takeoff_airport, landing_airport = await get_airports(db, input.takeoff_airport.id, input.landing_airport.id)
aircraft_id = await handle_aircraft_save(db, info.context.user_id, input.aircraft)
weather_takeoff,weather_landing = await asyncio.gather(
handle_weather_info(db, data['takeoff_datetime'], takeoff_airport),
handle_weather_info(db, data['landing_datetime'], landing_airport)
)
await db.flush()
print("XXXXXXXXXXXXX", weather_takeoff, weather_takeoff.id)
flight = await models.Flight.create(db, data={
**data,
"takeoff_weather_info_id": weather_takeoff.id,
"landing_weather_info_id": weather_landing.id,
@@ -177,6 +185,7 @@ class CreateFlightMutation:
"aircraft_id": aircraft_id,
"created_by_id": info.context.user_id
})
return flight
@strawberry.type
+19 -14
View File
@@ -16,7 +16,7 @@ weather_api = Weather()
async def handle_weather_info(db: AsyncSession, date_time: datetime, airport: models.Airport) -> models.WeatherInfo:
weather = await weather_api.get_weather_for_hour(date_time.astimezone(), (airport.gps_latitude, airport.gps_longitude))
return await models.WeatherInfo.create(db_session=db, data={
model = models.WeatherInfo(**{
"datetime": weather['datetime'],
"qnh": weather['pressure_msl'],
"temperature_surface": weather['temperature_2m'],
@@ -27,6 +27,9 @@ async def handle_weather_info(db: AsyncSession, date_time: datetime, airport: mo
"wind_speed_surface": weather['windspeed_10m'],
"wind_direction_surface": weather['winddirection_10m'],
})
db.add(model)
return model
async def handle_track_edit(db: AsyncSession, flight: models.Flight, track: List[ComboboxInput], user_id: int):
@@ -48,7 +51,7 @@ async def handle_track_edit(db: AsyncSession, flight: models.Flight, track: List
poi_object = poi_map.get(item.id)
if not poi_object:
poi_object = await models.PointOfInterest.create(db, data=dict(created_by_id=user_id, name=item.name))
poi_object = await models.PointOfInterest.create(db, data=dict(created_by_id=user_id, name=item.name, description=""))
await db.flush()
await models.FlightTrack.create(
@@ -63,19 +66,15 @@ async def handle_track_edit(db: AsyncSession, flight: models.Flight, track: List
async def handle_aircraft_save(db: AsyncSession, user_id: int, aircraft: ComboboxInput):
if aircraft.id:
return aircraft.id
else:
obj = await models.Aircraft.create(db, {
"call_sign": aircraft.name,
return await handle_combobox_save(
db, models.Aircraft, aircraft, user_id,
name_column="call_sign",
extra_data={
"description": "",
"model": "",
"seats": 2,
"manufacturer": "",
"created_by_id": user_id
})
await db.flush()
return obj.id
async def get_airports(db, takeoff_airport_id: int, landing_airport_id: int) -> Tuple[models.Airport, models.Airport]:
@@ -127,15 +126,21 @@ async def handle_copilots_edit(db: AsyncSession, copilots: List[ComboboxInput],
async def handle_combobox_save(
db: AsyncSession, model: Type[models.BaseModel],
db: AsyncSession,
model: Type[models.BaseModel],
input: ComboboxInput,
user_id: int,
name_column: str = "name"
name_column: str = "name",
extra_data: Optional[dict] = None
) -> int:
if input.id:
return input.id
else:
data = {name_column: input.name}
if not extra_data:
extra_data = {}
data = {name_column: input.name, **extra_data}
if hasattr(model, "created_by_id"):
data["created_by_id"] = user_id
+4 -2
View File
@@ -5,7 +5,7 @@ from strawberry.file_uploads import Upload
from database import models
from decorators.endpoints import authenticated_user_only
from graphql_schema.sqlalchemy_to_strawberry_type import strawberry_sqlalchemy_type, strawberry_sqlalchemy_input
from upload_utils import get_public_url, handle_file_upload, delete_file, parse_exif_info, generate_thumbnail, file_exists
from upload_utils import get_public_url, handle_file_upload, delete_file, parse_exif_info, generate_thumbnail, file_exists, resize_image
@strawberry_sqlalchemy_type(models.Photo)
@@ -57,7 +57,9 @@ class UploadPhotoMutation:
async def upload_photo(self, info, input: UploadPhotoInput) -> Photo:
path = get_photo_basepath(input.flight_id)
filename = await handle_file_upload(input.photo, path)
info.context.background_tasks.add_task(generate_thumbnail, path=path, filename=filename, size=(300, 200))
info.context.background_tasks.add_task(resize_image, path=path, filename=filename, new_width=2500)
info.context.background_tasks.add_task(generate_thumbnail, path=path, filename=filename, new_width=300)
exif_info = await parse_exif_info(path, filename)
+8 -1
View File
@@ -11,7 +11,7 @@ from database.models import User
from decorators.endpoints import authenticated_user_only
from decorators.error_logging import error_logging
from graphql_schema.sqlalchemy_to_strawberry_type import strawberry_sqlalchemy_type, strawberry_sqlalchemy_input
from upload_utils import handle_file_upload, delete_file, get_public_url
from upload_utils import handle_file_upload, delete_file, get_public_url, resize_image
@strawberry_sqlalchemy_type(User, exclude_fields=['password_hashed'])
@@ -81,6 +81,9 @@ class EditUserMutation:
delete_file(f"{user_image_path}/{user.avatar_image_filename}", silent=True)
data['avatar_image_filename'] = await handle_file_upload(input.avatar_image, user_image_path)
info.context.background_tasks.add_task(
resize_image, path=user_image_path, filename=data['avatar_image_filename'], new_width=400
)
if input.title_image:
if user.title_image_filename:
@@ -88,6 +91,10 @@ class EditUserMutation:
data['title_image_filename'] = await handle_file_upload(input.title_image, user_image_path)
info.context.background_tasks.add_task(
resize_image, path=user_image_path, filename=data['title_image_filename'], new_width=800
)
if input.old_password and input.new_password:
if not bcrypt.verify(input.old_password, user.password_hashed):
raise GraphQLError("Bad password")
+33 -4
View File
@@ -62,15 +62,44 @@ async def parse_exif_info(path: str, filename: str) -> dict:
return exif_info
async def generate_thumbnail(path: str, filename: str, size: Tuple[int, int]):
async def resize_image(path: str, filename: str, new_width: int, quality: int = 90, dest_path: str = None, dest_filename: str = None):
print("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
if not dest_path:
dest_path = path
if not dest_filename:
dest_filename = filename
try:
image = Image.open(f"{path}/{filename}")
image.thumbnail(size)
width, height = image.size
new_height = int(new_width * height / width)
image = image.resize((new_width, new_height), Image.LANCZOS)
check_directories(dest_path)
image.save(f"{dest_path}/{dest_filename}", 'JPEG', quality=quality)
except UnidentifiedImageError as e :
pass
print(e)
print("AAA^^^^^^^^^^^^AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
async def generate_thumbnail(path: str, filename: str, size: Tuple[int, int], quality: int = 90):
try:
image = Image.open(f"{path}/{filename}")
image = image.thumbnail(size, Image.LANCZOS)
check_directories(f"{path}/thumbs/")
image.save(f"{path}/thumbs/{filename}")
image.save(f"{path}/thumbs/{filename}", 'JPEG', quality=quality)
return await resize_image(path, filename, size, dest_path=f"{path}/thumbs/", dest_filename=filename)
except UnidentifiedImageError:
pass
def delete_file(path: str, silent: bool = False):
os.remove(path)
try:
os.remove(path)
except Exception:
if not silent:
raise