diff --git a/.gitignore b/.gitignore index 2a4e7eb..8567071 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .venv __pycache__ media -*.env \ No newline at end of file +*.env +test.py \ No newline at end of file diff --git a/src/app/core/config.py b/src/app/core/config.py index 0352acb..35c6750 100644 --- a/src/app/core/config.py +++ b/src/app/core/config.py @@ -1,4 +1,3 @@ -from typing import Optional from pathlib import Path from pydantic_settings import BaseSettings diff --git a/src/app/core/security.py b/src/app/core/security.py index 0b5597d..88b4f6d 100644 --- a/src/app/core/security.py +++ b/src/app/core/security.py @@ -1,5 +1,11 @@ -from datetime import datetime, timedelta -from typing import Any, Union +from datetime import ( + datetime, + timedelta +) +from typing import ( + Any, + Union +) from jose import jwt from passlib.context import CryptContext diff --git a/src/app/crud/base.py b/src/app/crud/base.py index 9a8b5c3..855381a 100644 --- a/src/app/crud/base.py +++ b/src/app/crud/base.py @@ -1,7 +1,18 @@ -from typing import Any, Dict, Generic, List, Optional, Type, TypeVar, Union +from typing import ( + Any, + Dict, + Generic, + List, + Optional, + Type, + TypeVar, + Union +) + +from pydantic import BaseModel from fastapi.encoders import jsonable_encoder -from pydantic import BaseModel + from sqlalchemy.future import select from sqlalchemy.orm import Session @@ -37,6 +48,14 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]): obj = await db.execute(q) return obj.scalars() + def sync_get_multi( + self, db: Session, *, skip: int = 0, limit: int = 100 + ) -> List[ModelType]: + + q = select(self.model).offset(skip).limit(limit).order_by(self.model.id.desc()) + obj = db.execute(q) + return obj.scalars() + async def create(self, db: Session, *, obj_in: CreateSchemaType) -> ModelType: obj_in_data = jsonable_encoder(obj_in) db_obj = self.model(**obj_in_data) # type: ignore diff --git a/src/app/crud/crud_user.py b/src/app/crud/crud_user.py index d84c42a..c588f65 100644 --- a/src/app/crud/crud_user.py +++ b/src/app/crud/crud_user.py @@ -15,6 +15,11 @@ class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]): obj = await db.execute(q) return obj.scalar_one_or_none() + def sync_get_by_email(self, db: Session, *, email: str) -> Optional[User]: + q = select(self.model).where(self.model.email == email) + obj = db.execute(q) + return obj.scalar_one_or_none() + async def create(self, db: Session, *, obj_in: UserCreate) -> User: db_obj = User( email=obj_in.email, @@ -29,6 +34,20 @@ class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]): return db_obj + def sync_create(self, db: Session, *, obj_in: UserCreate) -> User: + db_obj = User( + email=obj_in.email, + hashed_password=get_password_hash(obj_in.password), + username=obj_in.username, + is_superuser=obj_in.is_superuser, + ) + + db.add(db_obj) + db.commit() + db.refresh(db_obj) + + return db_obj + async def update( self, db: Session, *, db_obj: User, obj_in: Union[UserUpdate, Dict[str, Any]] ) -> User: diff --git a/src/app/db/base_class.py b/src/app/db/base_class.py index 4d4414d..df4c135 100644 --- a/src/app/db/base_class.py +++ b/src/app/db/base_class.py @@ -1,7 +1,10 @@ from typing import Any from sqlalchemy.ext.declarative import as_declarative, declared_attr -from sqlalchemy import DateTime, Column +from sqlalchemy import ( + DateTime, + Column +) from sqlalchemy.sql import func diff --git a/src/app/main.py b/src/app/main.py index 5f40f7c..a3f06e9 100644 --- a/src/app/main.py +++ b/src/app/main.py @@ -11,7 +11,7 @@ from app.schemas.login import LoginForm from app.schemas.post import Post, PostCreate, PostUpdate from sqlalchemy.ext.asyncio import AsyncSession from app.schemas.user import User, UserCreate -from fastapi.responses import HTMLResponse +from fastapi.responses import FileResponse, HTMLResponse from app.views.depends import get_async_db, handle_image from typing import Annotated, Any @@ -46,6 +46,11 @@ async def validation_exception_handler(request, exc): return await request_validation_exception_handler(request, exc) +@app.exception_handler(404) +async def custom_404_handler(_, __): + return FileResponse(settings.STATIC_FOLDER / '404.jpg') + + # @app.post("/login", response_model=JWTToken) # async def login( # db: AsyncSession = Depends(get_async_db), diff --git a/src/app/models/post.py b/src/app/models/post.py index 8f91191..775cd67 100644 --- a/src/app/models/post.py +++ b/src/app/models/post.py @@ -1,3 +1,4 @@ +from contextlib import contextmanager from slugify import slugify from sqlalchemy.orm.base import NO_VALUE @@ -34,16 +35,15 @@ from app.core.config import settings def generate_slug(target, value, oldvalue, initiator): slug = slugify(value) - db = next(get_db()) + with contextmanager(get_db)() as db: + number = 1 + temp_slug = slug - number = 1 - temp_slug = slug + while db.query(Post).filter(Post.slug == temp_slug).first() is not None: + temp_slug = f'{slug}-{number}' + number += 1 - while db.query(Post).filter(Post.slug == temp_slug).first() is not None: - temp_slug = f'{slug}-{number}' - number += 1 - - target.slug = temp_slug + target.slug = temp_slug listen(Post.title, 'set', generate_slug) diff --git a/src/app/schemas/__init__.py b/src/app/schemas/__init__.py index 8e7cc3e..94e4d11 100644 --- a/src/app/schemas/__init__.py +++ b/src/app/schemas/__init__.py @@ -10,7 +10,8 @@ from .user import ( User, UserCreate, UserInDBBase, - UserUpdate + UserUpdate, + UserBase ) from .login import ( JWTToken, diff --git a/src/app/schemas/login.py b/src/app/schemas/login.py index f9d5d60..3c0d13c 100644 --- a/src/app/schemas/login.py +++ b/src/app/schemas/login.py @@ -1,5 +1,6 @@ from dataclasses import dataclass from typing import Optional + from fastapi import Form from pydantic import ( diff --git a/src/app/schemas/user.py b/src/app/schemas/user.py index 39d8605..593a307 100644 --- a/src/app/schemas/user.py +++ b/src/app/schemas/user.py @@ -1,6 +1,9 @@ from typing import Optional -from pydantic import BaseModel, EmailStr +from pydantic import ( + BaseModel, + EmailStr +) class UserBase(BaseModel): diff --git a/src/app/templates/admin/login.html b/src/app/templates/admin/login.html index 2204ec6..13ea62d 100644 --- a/src/app/templates/admin/login.html +++ b/src/app/templates/admin/login.html @@ -13,28 +13,53 @@