added CRUD category

parent 775478f1
from uuid import UUID
from starlette import status
import fastapi
from tortoise.exceptions import ValidationError
from base_ctrl import BaseController
from exceptions import common as common_exc, http as http_exc
from .services import CategoryService
class CategoryController(BaseController):
category_service = CategoryService()
async def get_list(self, **kwargs):
return await self.category_service.get_category_list(**kwargs)
async def get(self, id: UUID):
try:
return await self.category_service.get_category(id)
except common_exc.NotFoundException as e:
raise http_exc.HTTPNotFoundException(detail=str(e))
async def create(self, **kwargs):
try:
return await self.category_service.create_category(**kwargs)
except common_exc.CreateException as e:
raise http_exc.HTTPBadRequestException(detail=str(e))
except ValidationError as e:
raise http_exc.HTTPBadRequestException(detail=f"Validation error: {str(e)}")
async def update(self, id: UUID, **kwargs):
try:
return await self.category_service.update_category(id, **kwargs)
except common_exc.UpdateException as e:
raise http_exc.HTTPBadRequestException(detail=str(e))
async def delete(self, id: UUID):
try:
await self.category_service.delete_category(id)
return fastapi.responses.Response(status_code=status.HTTP_204_NO_CONTENT)
except common_exc.DeleteException as e:
raise http_exc.HTTPBadRequestException(detail=str(e))
except common_exc.NotFoundException as e:
raise http_exc.HTTPNotFoundException(detail=str(e))
from uuid import UUID
import fastapi
from .schemas import CategoryBaseSchema
from .ctrl import CategoryController
router = fastapi.APIRouter(prefix='/categories', tags=['Category'])
ctrl = CategoryController()
@router.get('')
async def get_categories(query: CategoryBaseSchema = fastapi.Depends()):
return await ctrl.get_list(**query.model_dump(exclude_none=True))
@router.get('/{id}')
async def get_category(id: UUID):
return await ctrl.get(id)
@router.post('')
async def create_category(body: CategoryBaseSchema):
return await ctrl.create(**body.model_dump(exclude_none=True))
@router.patch('/{id}')
async def update_category(id: UUID, body: CategoryBaseSchema):
return await ctrl.update(id, **body.model_dump(exclude_none=True))
@router.delete('/{id}')
async def delete_category(id: UUID):
return await ctrl.delete(id)
from uuid import UUID
from pydantic import BaseModel, ConfigDict
class CategoryBaseSchema(BaseModel):
name: str | None = None
class CategoryIdSchema(BaseModel):
id: UUID
model_config = ConfigDict(from_attributes=True)
class CategorySchema(CategoryBaseSchema, CategoryIdSchema):
pass
from uuid import UUID
from db.repositories import CategoryRepository
from .schemas import CategorySchema
class CategoryService:
category_repository = CategoryRepository()
async def get_category_list(self, **kwargs):
categories = await self.category_repository.get_list(**kwargs)
return [CategorySchema.model_validate(category) for category in categories]
async def get_category(self, id: UUID):
category = await self.category_repository.get(id)
return CategorySchema.model_validate(category)
async def create_category(self, **kwargs):
category = await self.category_repository.create(**kwargs)
return CategorySchema.model_validate(category)
async def update_category(self, id: UUID, **kwargs):
category = await self.category_repository.update(id, **kwargs)
return CategorySchema.model_validate(category)
async def delete_category(self, id: UUID):
return await self.category_repository.delete(id)
...@@ -4,6 +4,7 @@ from .status.routes import router as status_route ...@@ -4,6 +4,7 @@ from .status.routes import router as status_route
from .type.routes import router as type_route from .type.routes import router as type_route
from .task.routes import router as task_route from .task.routes import router as task_route
from .user.routes import router as user_route from .user.routes import router as user_route
from .category.routes import router as category_route
router = APIRouter(prefix='/api') router = APIRouter(prefix='/api')
...@@ -11,3 +12,4 @@ router.include_router(status_route) ...@@ -11,3 +12,4 @@ router.include_router(status_route)
router.include_router(type_route) router.include_router(type_route)
router.include_router(task_route) router.include_router(task_route)
router.include_router(user_route) router.include_router(user_route)
router.include_router(category_route)
...@@ -43,6 +43,10 @@ class Task(BaseModel): ...@@ -43,6 +43,10 @@ class Task(BaseModel):
through='types_tasks' through='types_tasks'
) )
priority = fields.CharEnumField(enum_type=PriorityEnum, default=PriorityEnum.LOW) priority = fields.CharEnumField(enum_type=PriorityEnum, default=PriorityEnum.LOW)
category = fields.ForeignKeyField(
'models.Category', related_name='category_tasks',
on_delete=fields.OnDelete.SET_NULL, null=True
)
def __str__(self): def __str__(self):
return self.title return self.title
......
...@@ -2,7 +2,7 @@ import tortoise ...@@ -2,7 +2,7 @@ import tortoise
from tortoise.expressions import Q from tortoise.expressions import Q
from .models import ( from .models import (
Status, Type, Task, User, Comment Status, Type, Task, User, Comment, Category
) )
from exceptions import common as common_exc from exceptions import common as common_exc
...@@ -98,3 +98,7 @@ class UserRepository(BaseRepository): ...@@ -98,3 +98,7 @@ class UserRepository(BaseRepository):
class CommentRepository(BaseRepository): class CommentRepository(BaseRepository):
model = Comment model = Comment
class CategoryRepository(BaseRepository):
model = Category
from tortoise import BaseDBAsyncClient
async def upgrade(db: BaseDBAsyncClient) -> str:
return """
CREATE TABLE IF NOT EXISTS "categories" (
"id" UUID NOT NULL PRIMARY KEY,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"name" VARCHAR(255) NOT NULL
);"""
async def downgrade(db: BaseDBAsyncClient) -> str:
return """
DROP TABLE IF EXISTS "categories";"""
from tortoise import BaseDBAsyncClient
async def upgrade(db: BaseDBAsyncClient) -> str:
return """
ALTER TABLE "tasks" ADD "category_id" UUID;
ALTER TABLE "tasks" ADD CONSTRAINT "fk_tasks_categori_3e76a3ba" FOREIGN KEY ("category_id") REFERENCES "categories" ("id") ON DELETE SET NULL;"""
async def downgrade(db: BaseDBAsyncClient) -> str:
return """
ALTER TABLE "tasks" DROP CONSTRAINT "fk_tasks_categori_3e76a3ba";
ALTER TABLE "tasks" DROP COLUMN "category_id";"""
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment