Реализация crud и его добавление в RESTfull

This commit is contained in:
2024-08-01 01:21:32 +09:00
parent bdd764c411
commit d02ca36777
15 changed files with 361 additions and 28 deletions

View File

@ -0,0 +1,9 @@
from fastapi import APIRouter
from core.settings import settings
from .api_v1 import router as v1_router
router = APIRouter(
prefix= settings.api.prefix,
tags=["Основной роутер"]
)
router.include_router(v1_router)

View File

@ -1,7 +0,0 @@
from fastapi import APIRouter
router = APIRouter()
@router.get("/hello")
async def say_world():
return {"msg":"Hello WORLD!"}

View File

@ -0,0 +1,13 @@
from fastapi import APIRouter
from core.settings import settings
from .login import router as login_router
from .user import router as user_router
router = APIRouter(
prefix=settings.api.v1.prefix,
)
router.include_router(
user_router
)
router.include_router(
login_router
)

View File

@ -0,0 +1,53 @@
from fastapi import APIRouter, Depends
from core.settings import settings
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Annotated
from core.models import db_helper
from repo.schemas import LoginCreate,LoginRead, LoginUpdate
import repo.crud.login as crud
router = APIRouter(
prefix=settings.api.v1.login,
tags=["Login"]
)
@router.get("/", response_model=list[LoginRead])
async def get_all_logins(
session: Annotated[AsyncSession, Depends(db_helper.session_getter)]
):
logins = await crud.get_all_logins(session=session)
return logins
@router.get("/{login_id}", response_model=LoginRead)
async def get_login(
session: Annotated[AsyncSession, Depends(db_helper.session_getter)],
login_id: int
):
login = await crud.get_login(
session=session,
login_id=login_id
)
return login
@router.post("/", response_model=LoginRead)
async def create_login(
session: Annotated[AsyncSession, Depends(db_helper.session_getter)],
login_create: LoginCreate
):
login = await crud.create_login(
session=session,
login_create=login_create
)
return login
@router.patch("/{login_id}", response_model=LoginRead)
async def update_login(
session: Annotated[AsyncSession, Depends(db_helper.session_getter)],
login_id: int,
login_update: LoginUpdate
):
login = await crud.update_login(
session=session,
login_id=login_id,
login_update=login_update
)
return login

View File

@ -0,0 +1,57 @@
from fastapi import APIRouter, Depends
from core.settings import settings
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Annotated
from repo.schemas import UserRead, UserCreate, UserUpdate
from core.models import db_helper
import repo.crud.user as crud
router = APIRouter(
prefix=settings.api.v1.user,
tags=["Users"]
)
@router.get("/", response_model=list[UserRead])
async def get_all_users(
session: Annotated[AsyncSession, Depends(db_helper.session_getter)]
):
users = await crud.get_all_users(session=session)
return users
@router.get("/{user_id}", response_model=UserRead)
async def get_user(
session: Annotated[AsyncSession, Depends(db_helper.session_getter)],
user_id: int
):
users = await crud.get_user(
session=session,
user_id=user_id
)
return users
@router.post("/", response_model=UserRead)
async def create_user(
session: Annotated[AsyncSession, Depends(db_helper.session_getter)],
user_create: UserCreate
):
users = await crud.create_user(
session=session,
user_create=user_create
)
return users
@router.patch("/{user_id}", response_model=UserRead)
async def update_user(
session: Annotated[AsyncSession, Depends(db_helper.session_getter)],
user_id: int,
user_update: UserUpdate
):
users = await crud.update_user(
session=session,
user_id=user_id,
user_update=user_update
)
return users

View File

@ -1,7 +0,0 @@
from fastapi import APIRouter
router = APIRouter()
@router.get("/hello")
async def say_hello():
return {"msg":"hello"}

View File

@ -5,6 +5,15 @@ class RunSettings(BaseModel):
host: str = "0.0.0.0"
port: int = 8000
class APIV1Prefix(BaseModel):
prefix:str = "/v1"
user:str = "/user"
login:str = "/login"
class APIPrefix(BaseModel):
prefix:str = "/api"
v1: APIV1Prefix = APIV1Prefix()
class DatabaseConfig(BaseModel):
url: str
echo:bool=False
@ -28,5 +37,6 @@ class Settings(BaseSettings):
)
run: RunSettings = RunSettings()
db: DatabaseConfig
api: APIPrefix = APIPrefix()
settings = Settings()

View File

@ -2,8 +2,7 @@ import uvicorn
from fastapi import FastAPI, HTTPException
from fastapi.responses import ORJSONResponse
from core.settings import settings
from api.main_router import router as main_router
from api.another_router import router as another_router
from api import router
from core.models import db_helper
from contextlib import asynccontextmanager
@ -21,15 +20,6 @@ main_app = FastAPI(
#api/hello
main_app.include_router(
router=main_router,
prefix="/api",
tags=["Основной роутер"]
)
main_app.include_router(
router=another_router,
prefix="/another",
tags=["Побочный роутер"]
)
main_app.include_router(router)
if __name__ == "__main__":
uvicorn.run(main_app, host=settings.run.host, port=settings.run.port)

View File

@ -0,0 +1,58 @@
from typing import Sequence
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, delete, update
from ..schemas import LoginRead, LoginCreate, LoginUpdate
from ..models import LoginModel
from utils.hashing import get_password_hash
async def get_all_logins(
session: AsyncSession
) -> Sequence[LoginModel]:
stmt = select(LoginModel).order_by(LoginModel.id)
result = await session.scalars(stmt)
return result.all()
async def get_login(
session: AsyncSession,
login_id: int
) -> LoginModel:
db_login = await session.get(LoginModel,login_id)
if db_login is None:
return None
return db_login
async def create_login(
session:AsyncSession,
login_create: LoginCreate
) -> LoginModel:
login = LoginModel(**login_create.model_dump())
login.password = get_password_hash(login.password)
session.add(login)
await session.commit()
return login
async def delete_login(
session: AsyncSession,
login_id: int
) -> LoginModel:
db_login = await session.get(LoginModel,login_id)
if db_login is None:
return None
stmt = delete(LoginModel).filter(LoginModel.id == login_id)
await session.execute(stmt)
await session.commit()
return db_login.one_or_none()
async def update_login(
session:AsyncSession,
login_id: int,
login_update: LoginUpdate
) -> LoginModel:
db_login = await session.get(LoginModel,login_id)
if db_login is None:
return None
for var, value in vars(login_update).items():
setattr(db_login, var, value if var != "password" else get_password_hash(value)) if value else None
await session.commit()
return db_login

View File

@ -0,0 +1,58 @@
from typing import Sequence
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, delete, update
from ..schemas import UserRead, UserCreate,UserUpdate
from ..models import UserModel
async def get_all_users(
session: AsyncSession
) -> Sequence[UserModel]:
stmt = select(UserModel).order_by(UserModel.id)
result = await session.scalars(stmt)
return result.all()
async def get_user(
session: AsyncSession,
user_id: int
) -> UserModel:
db_user = await session.get(UserModel, user_id)
if db_user is None:
return None
return db_user
async def create_user(
session:AsyncSession,
user_create: UserCreate
) -> UserModel:
user = UserModel(**user_create.model_dump())
session.add(user)
await session.commit()
return user
async def delete_user(
session: AsyncSession,
user_id: int
) -> UserModel:
db_user = await session.get(UserModel, user_id)
if db_user is None:
return None
stmt = delete(UserModel).filter(UserModel.id == user_id)
await session.execute(stmt)
await session.commit()
return db_user.one_or_none()
async def update_user(
session:AsyncSession,
user_id: int,
user_update: UserUpdate
) -> UserModel:
db_user = await session.get(UserModel, user_id)
if db_user is None:
return None
for var, value in vars(user_update).items():
setattr(db_user, var, value) if value else None
await session.commit()
await session.refresh(db_user)
return db_user

View File

@ -1,2 +1,33 @@
from pydantic import BaseModel
from pydantic import BaseModel, EmailStr
from typing import Optional, Sequence
class LoginBase(BaseModel):
username:str
password:str
class LoginUpdate(BaseModel):
username:Optional[str] = None
password:Optional[str] = None
class LoginCreate(LoginBase):
pass
class LoginRead(LoginBase):
id:int
class UserUpdate(BaseModel):
firstname:Optional[str] = None
lastname:Optional[str] = None
age: Optional[int] = None
email: Optional[EmailStr] = None
class UserBase(UserUpdate):
login_id: int
class UserCreate(UserBase):
pass
class UserRead(UserBase):
id:int

View File

@ -0,0 +1,9 @@
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
def get_password_hash(password):
return pwd_context.hash(password)