Config -> common.py, added paths, respond.py functions and templates

This commit is contained in:
DarkCat09 2023-02-18 21:17:16 +04:00
parent bfea5eeb06
commit 804e07b555
6 changed files with 182 additions and 8 deletions

17
app/common.py Normal file
View file

@ -0,0 +1,17 @@
import secrets
from fastapi.templating import Jinja2Templates
from pydantic import BaseSettings
class Settings(BaseSettings):
secret_key: str = secrets.token_hex(32)
templates_dir: str = '../templates'
static_dir: str = '../static'
settings = Settings()
templates = Jinja2Templates(
directory=settings.templates_dir,
)

50
app/errors.py Normal file
View file

@ -0,0 +1,50 @@
"""Custom error pages for FastAPI app"""
from pathlib import Path
from fastapi import Request, Response
from fastapi import HTTPException
from . import paths
from . import respond
from .common import settings
# Add other HTTP error codes
codes = [404, 500]
class ErrorsPaths(paths.Paths):
"""Sets up custom error pages,
inherited from paths.Paths"""
def add_paths(self) -> None:
for code in codes:
self.add_handler(code)
def add_handler(self, code: int) -> None:
"""Adds an error handler to FastAPI app.
Only for internal use!
Args:
code (int): HTTP error code
"""
tmpl_dir = (
Path(__file__).parent /
settings.templates_dir
)
file = tmpl_dir / f'{code}.html'
if not file.exists():
return
@self.app.exception_handler(code)
async def handler(req: Request, exc: HTTPException) -> Response:
return respond.with_tmpl(
f'{code}.html',
code=code,
request=req,
exc=exc,
)

View file

@ -1,16 +1,9 @@
import secrets
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from pydantic import BaseSettings
#from .common import settings, templates
class Settings(BaseSettings):
secret_key: str = secrets.token_hex(32)
settings = Settings()
app = FastAPI()
app.mount(
'/static',

16
app/pages.py Normal file
View file

@ -0,0 +1,16 @@
"""Main FastAPI paths"""
from fastapi import Response
from . import paths
from . import respond
class MainPaths(paths.Paths):
"""Main FastAPI app paths, inherits paths.Paths"""
def add_paths(self) -> None:
@self.app.get('/')
def index() -> Response:
return respond.with_tmpl('index.html')

21
app/paths.py Normal file
View file

@ -0,0 +1,21 @@
import abc
from fastapi import FastAPI
class Paths(abc.ABC):
"""Abstract class for storing paths for FastAPI app"""
def __init__(self, app: FastAPI) -> None:
"""Abstract class for storing paths
for FastAPI app
Args:
app (FastAPI): Application object
"""
self.app = app
@abc.abstractmethod
def add_paths(self) -> None:
"""Add paths to the FastAPI application"""

77
app/respond.py Normal file
View file

@ -0,0 +1,77 @@
import os
import mimetypes
from typing import Optional, Mapping
from fastapi import Response
from fastapi.responses import FileResponse
from starlette.background import BackgroundTask
from .common import templates
def with_tmpl(
name: str,
code: int = 200,
headers: Optional[Mapping[str, str]] = None,
background: Optional[BackgroundTask] = None,
**context) -> Response:
"""Render a Jinja2 template and return Response object.
`response_class` parameter is not needed
Args:
name (str): Template filename
code (int, optional): HTTP response code
headers (Optional[Mapping[str, str]], optional):
Additional headers, passed to Response constructor
background (Optional[BackgroundTask], optional):
Background task, passed to Response constructor
Returns:
FastAPI's TemplateResponse object
"""
return templates.TemplateResponse(
name=name,
context=context,
status_code=code,
headers=headers,
background=background,
)
def with_file(
path: os.PathLike,
mime: Optional[str] = None,
code: int = 200,
headers: Optional[Mapping[str, str]] = None,
background: Optional[BackgroundTask] = None) -> FileResponse:
"""Send a file specified in `path`
automatically guessing mimetype if `mime` is None
Args:
path (os.PathLike): File path
mime (Optional[str], optional): File mimetype
code (int, optional): HTTP response code
headers (Optional[Mapping[str, str]], optional):
Additional headers, passed to Response constructor
background (Optional[BackgroundTask], optional):
Background task, passed to Response constructor
Returns:
FileResponse: FastAPI's FileResponse object
"""
return FileResponse(
path=path,
media_type=(
mime or
mimetypes.guess_type(path)[0]
),
status_code=code,
headers=headers,
background=background,
)
# Alias
with_template = with_tmpl