From 9a3a6eea029f2d99b62ee5f0a733ec8f80fc037e Mon Sep 17 00:00:00 2001 From: Eeap Date: Tue, 17 Oct 2023 00:27:28 +0900 Subject: [PATCH 1/7] feat: add schema, model about room, post --- app/db/base.py | 2 ++ app/models/domain/posts.py | 12 ++++++++++++ app/models/domain/rooms.py | 17 +++++++++++++++++ app/models/schemas/posts.py | 22 ++++++++++++++++++++++ app/models/schemas/rooms.py | 16 ++++++++++++++++ app/models/schemas/users.py | 9 ++++++--- app/resources/status.py | 4 ++++ 7 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 app/models/domain/posts.py create mode 100644 app/models/domain/rooms.py create mode 100644 app/models/schemas/posts.py create mode 100644 app/models/schemas/rooms.py create mode 100644 app/resources/status.py diff --git a/app/db/base.py b/app/db/base.py index 61ae182..8be31d8 100644 --- a/app/db/base.py +++ b/app/db/base.py @@ -2,3 +2,5 @@ # imported by Alembic from app.db.base_class import Base # noqa from app.models.schemas.users import User # noqa +from app.models.schemas.posts import Post # noqa +from app.models.schemas.rooms import Room # noqa diff --git a/app/models/domain/posts.py b/app/models/domain/posts.py new file mode 100644 index 0000000..17207c1 --- /dev/null +++ b/app/models/domain/posts.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel +from typing import Optional +from app.resources.status import Status + +class PostCreate(BaseModel): + title: str + content: str + status: Status + category: str + image: bool + user_id: Optional[int] = None + diff --git a/app/models/domain/rooms.py b/app/models/domain/rooms.py new file mode 100644 index 0000000..4f70e9a --- /dev/null +++ b/app/models/domain/rooms.py @@ -0,0 +1,17 @@ +from typing import Optional +from pydantic import BaseModel +import datetime +from app.resources.status import Status + +class RoomCreate(BaseModel): + post_id: Optional[int] = None + starting_price: Optional[int] = None + price: int + auction: bool + deadline: datetime.datetime + title: str + content: str + status: Status + category: str + image: bool + diff --git a/app/models/schemas/posts.py b/app/models/schemas/posts.py new file mode 100644 index 0000000..6008eed --- /dev/null +++ b/app/models/schemas/posts.py @@ -0,0 +1,22 @@ +from sqlalchemy import Boolean, Column, Integer, String, DateTime, ForeignKey, Enum +from sqlalchemy.orm import relationship +from app.db.base_class import Base +from typing import TYPE_CHECKING +from app.resources.status import Status +if TYPE_CHECKING: + from .users import User # noqa: F401 + from .rooms import Room # noqa: F401 + +class Post(Base): + id = Column(Integer, primary_key=True, autoincrement=True, index=True) + title = Column(String(255), index=True) + content = Column(String(255), index=True) + user_id = Column(Integer) + user_id = Column(Integer, ForeignKey("user.id")) + user = relationship("User", back_populates="posts") + status = Column(Enum(Status), nullable=False, default=Status.PROCESSING) + created_at = Column(DateTime, nullable=False) + category = Column(String(255), index=True) + image = Column(Boolean(), default=False) + room = relationship("Room", back_populates="post") + diff --git a/app/models/schemas/rooms.py b/app/models/schemas/rooms.py new file mode 100644 index 0000000..3ddf4cb --- /dev/null +++ b/app/models/schemas/rooms.py @@ -0,0 +1,16 @@ +from sqlalchemy import Boolean, Column, Integer, DateTime, ForeignKey +from sqlalchemy.orm import relationship +from typing import TYPE_CHECKING +from app.db.base_class import Base + +if TYPE_CHECKING: + from .posts import Post # noqa: F401 + +class Room(Base): + id = Column(Integer, primary_key=True, autoincrement=True, index=True) + starting_price = Column(Integer) + price = Column(Integer,nullable=False) + auction = Column(Boolean(), default=False) + deadline = Column(DateTime, nullable=False) + post_id = Column(Integer, ForeignKey("post.id")) + post = relationship("Post", back_populates="room") diff --git a/app/models/schemas/users.py b/app/models/schemas/users.py index 7da74be..3d2914b 100644 --- a/app/models/schemas/users.py +++ b/app/models/schemas/users.py @@ -1,9 +1,12 @@ -from sqlalchemy import Boolean, Column, Integer, String - +from sqlalchemy import Column, Integer, String +from sqlalchemy.orm import relationship from app.db.base_class import Base - +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from .posts import Post # noqa: F401 class User(Base): id = Column(Integer, primary_key=True, autoincrement=True, index=True) username = Column(String(255), index=True) email = Column(String(255), unique=True, index=True, nullable=False) + posts = relationship("Post", back_populates="user") diff --git a/app/resources/status.py b/app/resources/status.py new file mode 100644 index 0000000..adf03ac --- /dev/null +++ b/app/resources/status.py @@ -0,0 +1,4 @@ +import enum +class Status(enum.Enum): + COMPLETED = "COMPLETED" + PROCESSING = "PROCESSING" From 6d7a7f32971b1a660e732426c5d4cdb207551b95 Mon Sep 17 00:00:00 2001 From: Eeap Date: Tue, 17 Oct 2023 00:27:48 +0900 Subject: [PATCH 2/7] chore: fix api prefix url --- app/core/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/core/config.py b/app/core/config.py index 011694b..64c07d0 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -11,7 +11,7 @@ class Settings(BaseSettings): config: Config = Config(".env") - API_PREFIX: str = "/api" + API_PREFIX: str = "/api/v1" JWT_TOKEN_PREFIX: str = "Token" VERSION: str = "1.0.0" From 7f199bf2a136aa4ac5d2a32d27270491bd00399f Mon Sep 17 00:00:00 2001 From: Eeap Date: Tue, 17 Oct 2023 00:28:20 +0900 Subject: [PATCH 3/7] feat: add create market post route & method --- app/api/routes/api.py | 2 ++ app/api/routes/rooms.py | 31 +++++++++++++++++++++++++++++++ app/crud/__init__.py | 0 app/crud/crud_posts.py | 18 ++++++++++++++++++ app/crud/crud_rooms.py | 26 ++++++++++++++++++++++++++ 5 files changed, 77 insertions(+) create mode 100644 app/api/routes/rooms.py create mode 100644 app/crud/__init__.py create mode 100644 app/crud/crud_posts.py create mode 100644 app/crud/crud_rooms.py diff --git a/app/api/routes/api.py b/app/api/routes/api.py index c3807f7..233c486 100644 --- a/app/api/routes/api.py +++ b/app/api/routes/api.py @@ -1,7 +1,9 @@ from fastapi import APIRouter from app.api.routes import users +from app.api.routes import rooms router = APIRouter() router.include_router(users.router, tags=["users"], prefix="/user") +router.include_router(rooms.router, tags=["rooms"]) diff --git a/app/api/routes/rooms.py b/app/api/routes/rooms.py new file mode 100644 index 0000000..ffa545e --- /dev/null +++ b/app/api/routes/rooms.py @@ -0,0 +1,31 @@ +import logging +from typing import Any +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.orm import Session +from app.api.dependencies import database +from app.models.domain import rooms +from app.crud import crud_rooms, crud_posts + +router = APIRouter() + + +@router.post("/create/room") +def create_room_posts(*, db: Session = Depends(database.get_db), room_in: rooms.RoomCreate) -> Any: + """ + Create new user. + """ + # post data create + post_data = crud_posts.create(db=db, obj_in=room_in) + print(post_data) + # room data create + room_data = crud_rooms.create(db=db, obj_in=room_in, post_id=post_data.id) + print(room_data) + if room_data and post_data: + return { + "message": "create success" + } + else: + raise HTTPException( + status_code=500, + detail="create failed", + ) diff --git a/app/crud/__init__.py b/app/crud/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/crud/crud_posts.py b/app/crud/crud_posts.py new file mode 100644 index 0000000..35f007a --- /dev/null +++ b/app/crud/crud_posts.py @@ -0,0 +1,18 @@ +from sqlalchemy.orm import Session +from app.models.domain import posts +from app.models.schemas.posts import Post +import datetime + +def create(db: Session, *, obj_in: posts.PostCreate) -> Post: + db_obj = Post( + title=obj_in.title, + content=obj_in.content, + status=obj_in.status, + category=obj_in.category, + image=obj_in.image, + created_at=datetime.datetime.today() + ) + db.add(db_obj) + db.commit() + db.refresh(db_obj) + return db_obj diff --git a/app/crud/crud_rooms.py b/app/crud/crud_rooms.py new file mode 100644 index 0000000..b103fec --- /dev/null +++ b/app/crud/crud_rooms.py @@ -0,0 +1,26 @@ +from sqlalchemy.orm import Session +from app.models.domain import rooms +from app.models.schemas.rooms import Room + + +def create(db: Session, *, obj_in: rooms.RoomCreate, post_id: int) -> Room: + db_obj = None + if obj_in.starting_price: + db_obj = Room( + starting_price=obj_in.starting_price, + price=obj_in.price, + auction=obj_in.auction, + deadline=obj_in.deadline, + post_id=post_id, + ) + else: + db_obj = Room( + price=obj_in.price, + auction=obj_in.auction, + deadline=obj_in.deadline, + post_id=post_id, + ) + db.add(db_obj) + db.commit() + db.refresh(db_obj) + return db_obj From 0c5e7ac9db98c1f2809f89388824959ca6b0a625 Mon Sep 17 00:00:00 2001 From: Eeap Date: Tue, 17 Oct 2023 00:28:55 +0900 Subject: [PATCH 4/7] chore: add docker build no cache --- docker-compose.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index cc589f2..d26a21a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,8 @@ services: app: - build: . + build: + no_cache: true + context: . ports: - "8000:8000" env_file: From 2c45ae1c043fe9b2567addcb3a15ddc4ae42f0f9 Mon Sep 17 00:00:00 2001 From: Eeap Date: Tue, 17 Oct 2023 00:50:00 +0900 Subject: [PATCH 5/7] chore: code formatting --- app/api/routes/rooms.py | 38 +++++++++++++++++------------------ app/crud/crud_posts.py | 25 ++++++++++++----------- app/crud/crud_rooms.py | 40 ++++++++++++++++++------------------- app/models/domain/posts.py | 14 ++++++------- app/models/domain/rooms.py | 22 ++++++++++---------- app/models/schemas/posts.py | 3 ++- app/models/schemas/rooms.py | 3 ++- app/models/schemas/users.py | 2 ++ app/resources/status.py | 6 ++++-- 9 files changed, 80 insertions(+), 73 deletions(-) diff --git a/app/api/routes/rooms.py b/app/api/routes/rooms.py index ffa545e..34811b2 100644 --- a/app/api/routes/rooms.py +++ b/app/api/routes/rooms.py @@ -10,22 +10,22 @@ @router.post("/create/room") -def create_room_posts(*, db: Session = Depends(database.get_db), room_in: rooms.RoomCreate) -> Any: - """ - Create new user. - """ - # post data create - post_data = crud_posts.create(db=db, obj_in=room_in) - print(post_data) - # room data create - room_data = crud_rooms.create(db=db, obj_in=room_in, post_id=post_data.id) - print(room_data) - if room_data and post_data: - return { - "message": "create success" - } - else: - raise HTTPException( - status_code=500, - detail="create failed", - ) +def create_room_posts( + *, db: Session = Depends(database.get_db), room_in: rooms.RoomCreate +) -> Any: + """ + Create new user. + """ + # post data create + post_data = crud_posts.create(db=db, obj_in=room_in) + print(post_data) + # room data create + room_data = crud_rooms.create(db=db, obj_in=room_in, post_id=post_data.id) + print(room_data) + if room_data and post_data: + return {"message": "create success"} + else: + raise HTTPException( + status_code=500, + detail="create failed", + ) diff --git a/app/crud/crud_posts.py b/app/crud/crud_posts.py index 35f007a..9539e52 100644 --- a/app/crud/crud_posts.py +++ b/app/crud/crud_posts.py @@ -3,16 +3,17 @@ from app.models.schemas.posts import Post import datetime + def create(db: Session, *, obj_in: posts.PostCreate) -> Post: - db_obj = Post( - title=obj_in.title, - content=obj_in.content, - status=obj_in.status, - category=obj_in.category, - image=obj_in.image, - created_at=datetime.datetime.today() - ) - db.add(db_obj) - db.commit() - db.refresh(db_obj) - return db_obj + db_obj = Post( + title=obj_in.title, + content=obj_in.content, + status=obj_in.status, + category=obj_in.category, + image=obj_in.image, + created_at=datetime.datetime.today(), + ) + db.add(db_obj) + db.commit() + db.refresh(db_obj) + return db_obj diff --git a/app/crud/crud_rooms.py b/app/crud/crud_rooms.py index b103fec..6bfc3e8 100644 --- a/app/crud/crud_rooms.py +++ b/app/crud/crud_rooms.py @@ -4,23 +4,23 @@ def create(db: Session, *, obj_in: rooms.RoomCreate, post_id: int) -> Room: - db_obj = None - if obj_in.starting_price: - db_obj = Room( - starting_price=obj_in.starting_price, - price=obj_in.price, - auction=obj_in.auction, - deadline=obj_in.deadline, - post_id=post_id, - ) - else: - db_obj = Room( - price=obj_in.price, - auction=obj_in.auction, - deadline=obj_in.deadline, - post_id=post_id, - ) - db.add(db_obj) - db.commit() - db.refresh(db_obj) - return db_obj + db_obj = None + if obj_in.starting_price: + db_obj = Room( + starting_price=obj_in.starting_price, + price=obj_in.price, + auction=obj_in.auction, + deadline=obj_in.deadline, + post_id=post_id, + ) + else: + db_obj = Room( + price=obj_in.price, + auction=obj_in.auction, + deadline=obj_in.deadline, + post_id=post_id, + ) + db.add(db_obj) + db.commit() + db.refresh(db_obj) + return db_obj diff --git a/app/models/domain/posts.py b/app/models/domain/posts.py index 17207c1..c37c0ec 100644 --- a/app/models/domain/posts.py +++ b/app/models/domain/posts.py @@ -2,11 +2,11 @@ from typing import Optional from app.resources.status import Status -class PostCreate(BaseModel): - title: str - content: str - status: Status - category: str - image: bool - user_id: Optional[int] = None +class PostCreate(BaseModel): + title: str + content: str + status: Status + category: str + image: bool + user_id: Optional[int] = None diff --git a/app/models/domain/rooms.py b/app/models/domain/rooms.py index 4f70e9a..1aa5d1b 100644 --- a/app/models/domain/rooms.py +++ b/app/models/domain/rooms.py @@ -3,15 +3,15 @@ import datetime from app.resources.status import Status -class RoomCreate(BaseModel): - post_id: Optional[int] = None - starting_price: Optional[int] = None - price: int - auction: bool - deadline: datetime.datetime - title: str - content: str - status: Status - category: str - image: bool +class RoomCreate(BaseModel): + post_id: Optional[int] = None + starting_price: Optional[int] = None + price: int + auction: bool + deadline: datetime.datetime + title: str + content: str + status: Status + category: str + image: bool diff --git a/app/models/schemas/posts.py b/app/models/schemas/posts.py index 6008eed..2c39ac7 100644 --- a/app/models/schemas/posts.py +++ b/app/models/schemas/posts.py @@ -3,10 +3,12 @@ from app.db.base_class import Base from typing import TYPE_CHECKING from app.resources.status import Status + if TYPE_CHECKING: from .users import User # noqa: F401 from .rooms import Room # noqa: F401 + class Post(Base): id = Column(Integer, primary_key=True, autoincrement=True, index=True) title = Column(String(255), index=True) @@ -19,4 +21,3 @@ class Post(Base): category = Column(String(255), index=True) image = Column(Boolean(), default=False) room = relationship("Room", back_populates="post") - diff --git a/app/models/schemas/rooms.py b/app/models/schemas/rooms.py index 3ddf4cb..4a4588e 100644 --- a/app/models/schemas/rooms.py +++ b/app/models/schemas/rooms.py @@ -6,10 +6,11 @@ if TYPE_CHECKING: from .posts import Post # noqa: F401 + class Room(Base): id = Column(Integer, primary_key=True, autoincrement=True, index=True) starting_price = Column(Integer) - price = Column(Integer,nullable=False) + price = Column(Integer, nullable=False) auction = Column(Boolean(), default=False) deadline = Column(DateTime, nullable=False) post_id = Column(Integer, ForeignKey("post.id")) diff --git a/app/models/schemas/users.py b/app/models/schemas/users.py index 3d2914b..9e85e7a 100644 --- a/app/models/schemas/users.py +++ b/app/models/schemas/users.py @@ -2,9 +2,11 @@ from sqlalchemy.orm import relationship from app.db.base_class import Base from typing import TYPE_CHECKING + if TYPE_CHECKING: from .posts import Post # noqa: F401 + class User(Base): id = Column(Integer, primary_key=True, autoincrement=True, index=True) username = Column(String(255), index=True) diff --git a/app/resources/status.py b/app/resources/status.py index adf03ac..02e6f0e 100644 --- a/app/resources/status.py +++ b/app/resources/status.py @@ -1,4 +1,6 @@ import enum + + class Status(enum.Enum): - COMPLETED = "COMPLETED" - PROCESSING = "PROCESSING" + COMPLETED = "COMPLETED" + PROCESSING = "PROCESSING" From 6648b11fab544b357c42a0945f94576c49537d1f Mon Sep 17 00:00:00 2001 From: Eeap Date: Tue, 17 Oct 2023 13:13:35 +0900 Subject: [PATCH 6/7] fix: fix filename written room with market --- app/api/routes/api.py | 4 ++-- app/api/routes/{rooms.py => markets.py} | 18 ++++++++---------- app/crud/{crud_rooms.py => crud_markets.py} | 10 +++++----- app/db/base.py | 2 +- app/models/domain/{rooms.py => markets.py} | 2 +- app/models/schemas/{rooms.py => markets.py} | 4 ++-- app/models/schemas/posts.py | 4 ++-- 7 files changed, 21 insertions(+), 23 deletions(-) rename app/api/routes/{rooms.py => markets.py} (51%) rename app/crud/{crud_rooms.py => crud_markets.py} (70%) rename app/models/domain/{rooms.py => markets.py} (91%) rename app/models/schemas/{rooms.py => markets.py} (87%) diff --git a/app/api/routes/api.py b/app/api/routes/api.py index 233c486..59a0e44 100644 --- a/app/api/routes/api.py +++ b/app/api/routes/api.py @@ -1,9 +1,9 @@ from fastapi import APIRouter from app.api.routes import users -from app.api.routes import rooms +from app.api.routes import markets router = APIRouter() router.include_router(users.router, tags=["users"], prefix="/user") -router.include_router(rooms.router, tags=["rooms"]) +router.include_router(markets.router, tags=["markets"], prefix="/market") diff --git a/app/api/routes/rooms.py b/app/api/routes/markets.py similarity index 51% rename from app/api/routes/rooms.py rename to app/api/routes/markets.py index 34811b2..3dc95d0 100644 --- a/app/api/routes/rooms.py +++ b/app/api/routes/markets.py @@ -3,26 +3,24 @@ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from app.api.dependencies import database -from app.models.domain import rooms -from app.crud import crud_rooms, crud_posts +from app.models.domain import markets +from app.crud import crud_markets, crud_posts router = APIRouter() -@router.post("/create/room") -def create_room_posts( - *, db: Session = Depends(database.get_db), room_in: rooms.RoomCreate +@router.post("/create") +def create_market_posts( + *, db: Session = Depends(database.get_db), market_in: markets.MarketCreate ) -> Any: """ Create new user. """ # post data create - post_data = crud_posts.create(db=db, obj_in=room_in) - print(post_data) + post_data = crud_posts.create(db=db, obj_in=market_in) # room data create - room_data = crud_rooms.create(db=db, obj_in=room_in, post_id=post_data.id) - print(room_data) - if room_data and post_data: + market_data = crud_markets.create(db=db, obj_in=market_in, post_id=post_data.id) + if market_data and post_data: return {"message": "create success"} else: raise HTTPException( diff --git a/app/crud/crud_rooms.py b/app/crud/crud_markets.py similarity index 70% rename from app/crud/crud_rooms.py rename to app/crud/crud_markets.py index 6bfc3e8..fbde1b3 100644 --- a/app/crud/crud_rooms.py +++ b/app/crud/crud_markets.py @@ -1,12 +1,12 @@ from sqlalchemy.orm import Session -from app.models.domain import rooms -from app.models.schemas.rooms import Room +from app.models.domain import markets +from app.models.schemas.markets import Market -def create(db: Session, *, obj_in: rooms.RoomCreate, post_id: int) -> Room: +def create(db: Session, *, obj_in: markets.MarketCreate, post_id: int) -> Market: db_obj = None if obj_in.starting_price: - db_obj = Room( + db_obj = Market( starting_price=obj_in.starting_price, price=obj_in.price, auction=obj_in.auction, @@ -14,7 +14,7 @@ def create(db: Session, *, obj_in: rooms.RoomCreate, post_id: int) -> Room: post_id=post_id, ) else: - db_obj = Room( + db_obj = Market( price=obj_in.price, auction=obj_in.auction, deadline=obj_in.deadline, diff --git a/app/db/base.py b/app/db/base.py index 8be31d8..4ef39c0 100644 --- a/app/db/base.py +++ b/app/db/base.py @@ -3,4 +3,4 @@ from app.db.base_class import Base # noqa from app.models.schemas.users import User # noqa from app.models.schemas.posts import Post # noqa -from app.models.schemas.rooms import Room # noqa +from app.models.schemas.markets import Market # noqa diff --git a/app/models/domain/rooms.py b/app/models/domain/markets.py similarity index 91% rename from app/models/domain/rooms.py rename to app/models/domain/markets.py index 1aa5d1b..00ed904 100644 --- a/app/models/domain/rooms.py +++ b/app/models/domain/markets.py @@ -4,7 +4,7 @@ from app.resources.status import Status -class RoomCreate(BaseModel): +class MarketCreate(BaseModel): post_id: Optional[int] = None starting_price: Optional[int] = None price: int diff --git a/app/models/schemas/rooms.py b/app/models/schemas/markets.py similarity index 87% rename from app/models/schemas/rooms.py rename to app/models/schemas/markets.py index 4a4588e..466e712 100644 --- a/app/models/schemas/rooms.py +++ b/app/models/schemas/markets.py @@ -7,11 +7,11 @@ from .posts import Post # noqa: F401 -class Room(Base): +class Market(Base): id = Column(Integer, primary_key=True, autoincrement=True, index=True) starting_price = Column(Integer) price = Column(Integer, nullable=False) auction = Column(Boolean(), default=False) deadline = Column(DateTime, nullable=False) post_id = Column(Integer, ForeignKey("post.id")) - post = relationship("Post", back_populates="room") + post = relationship("Post", back_populates="market") diff --git a/app/models/schemas/posts.py b/app/models/schemas/posts.py index 2c39ac7..affb17b 100644 --- a/app/models/schemas/posts.py +++ b/app/models/schemas/posts.py @@ -6,7 +6,7 @@ if TYPE_CHECKING: from .users import User # noqa: F401 - from .rooms import Room # noqa: F401 + from .markets import Market # noqa: F401 class Post(Base): @@ -20,4 +20,4 @@ class Post(Base): created_at = Column(DateTime, nullable=False) category = Column(String(255), index=True) image = Column(Boolean(), default=False) - room = relationship("Room", back_populates="post") + market = relationship("Market", back_populates="post") From e04aaf576374380b1335297edd6cbb14c8d6930b Mon Sep 17 00:00:00 2001 From: Eeap Date: Tue, 17 Oct 2023 20:44:55 +0900 Subject: [PATCH 7/7] refactor: upload post image in aws s3 bucket using boto3 --- app/api/routes/markets.py | 11 +++++++---- app/core/config.py | 5 +++++ app/crud/crud_posts.py | 19 +++++++++++++++++-- app/models/domain/markets.py | 1 - app/models/domain/posts.py | 1 - app/services/aws.py | 26 ++++++++++++++++++++++++++ requirements.txt | 8 ++++++++ 7 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 app/services/aws.py diff --git a/app/api/routes/markets.py b/app/api/routes/markets.py index 3dc95d0..10733ba 100644 --- a/app/api/routes/markets.py +++ b/app/api/routes/markets.py @@ -1,6 +1,6 @@ import logging -from typing import Any -from fastapi import APIRouter, Depends, HTTPException +from typing import Any, List +from fastapi import APIRouter, Depends, HTTPException, UploadFile from sqlalchemy.orm import Session from app.api.dependencies import database from app.models.domain import markets @@ -11,13 +11,16 @@ @router.post("/create") def create_market_posts( - *, db: Session = Depends(database.get_db), market_in: markets.MarketCreate + *, + db: Session = Depends(database.get_db), + files: List[UploadFile], + market_in: markets.MarketCreate = Depends() ) -> Any: """ Create new user. """ # post data create - post_data = crud_posts.create(db=db, obj_in=market_in) + post_data = crud_posts.create(db=db, obj_in=market_in, files=files) # room data create market_data = crud_markets.create(db=db, obj_in=market_in, post_id=post_data.id) if market_data and post_data: diff --git a/app/core/config.py b/app/core/config.py index 64c07d0..611211f 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -1,6 +1,8 @@ import logging import sys from typing import List, Any + +import boto3 from pydantic_settings import BaseSettings from loguru import logger from starlette.config import Config @@ -29,6 +31,9 @@ class Settings(BaseSettings): ALLOWED_HOSTS: List[str] = config( "ALLOWED_HOSTS", cast=CommaSeparatedStrings, default="" ) + BUCKET_NAME: str = config("BUCKET_NAME", cast=str) + AWS_ACCESS_KEY: str = config("AWS_ACCESS_KEY", cast=str) + AWS_SECRET_KEY: str = config("AWS_SECRET_KEY", cast=str) # logging configuration diff --git a/app/crud/crud_posts.py b/app/crud/crud_posts.py index 9539e52..1814c4e 100644 --- a/app/crud/crud_posts.py +++ b/app/crud/crud_posts.py @@ -1,19 +1,34 @@ from sqlalchemy.orm import Session from app.models.domain import posts from app.models.schemas.posts import Post +from app.services.aws import s3_upload +from fastapi import HTTPException +from fastapi import UploadFile +from typing import List import datetime -def create(db: Session, *, obj_in: posts.PostCreate) -> Post: +def create(db: Session, *, obj_in: posts.PostCreate, files: List[UploadFile]) -> Post: db_obj = Post( title=obj_in.title, content=obj_in.content, status=obj_in.status, category=obj_in.category, - image=obj_in.image, created_at=datetime.datetime.today(), ) + # image bool value insert + db_obj.image = True if files else False db.add(db_obj) db.commit() db.refresh(db_obj) + # if image exits, do uploading in s3 + if files: + s3_result = s3_upload( + files=files, post_id=db_obj.id, user_email="sumink0903@gmail.com" + ) + if not s3_result: + raise HTTPException( + status_code=500, + detail="s3 upload failed", + ) return db_obj diff --git a/app/models/domain/markets.py b/app/models/domain/markets.py index 00ed904..02c2e58 100644 --- a/app/models/domain/markets.py +++ b/app/models/domain/markets.py @@ -14,4 +14,3 @@ class MarketCreate(BaseModel): content: str status: Status category: str - image: bool diff --git a/app/models/domain/posts.py b/app/models/domain/posts.py index c37c0ec..1030baa 100644 --- a/app/models/domain/posts.py +++ b/app/models/domain/posts.py @@ -8,5 +8,4 @@ class PostCreate(BaseModel): content: str status: Status category: str - image: bool user_id: Optional[int] = None diff --git a/app/services/aws.py b/app/services/aws.py new file mode 100644 index 0000000..47d0dd3 --- /dev/null +++ b/app/services/aws.py @@ -0,0 +1,26 @@ +import boto3 +from botocore.exceptions import ClientError +from fastapi import UploadFile +from app.core.config import settings +from typing import List + + +def s3_upload(files: List[UploadFile], post_id: int, user_email: str) -> bool: + client = boto3.client( + "s3", + region_name="us-east-1", + aws_access_key_id=settings.AWS_ACCESS_KEY, + aws_secret_access_key=settings.AWS_SECRET_KEY, + ) + try: + for file in files: + new_filename = f"/{user_email}/{post_id}/{file.filename}" + client.upload_fileobj( + file.file, + settings.BUCKET_NAME, + new_filename, + ExtraArgs={"ContentType": file.content_type}, + ) + except ClientError as e: + return False + return True diff --git a/requirements.txt b/requirements.txt index e165500..081e7aa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,8 @@ anyio==3.7.1 astroid==3.0.1 bcrypt==4.0.1 black==23.9.1 +boto3==1.28.64 +botocore==1.31.64 cffi==1.16.0 click==8.1.7 cryptography==41.0.4 @@ -15,6 +17,7 @@ fastapi==0.103.2 h11==0.14.0 idna==3.4 isort==5.12.0 +jmespath==1.0.1 jwt==1.3.1 lists==1.3.0 loguru==0.7.2 @@ -30,10 +33,15 @@ pydantic-settings==2.0.3 pydantic_core==2.10.1 pylint==3.0.1 PyMySQL==1.1.0 +python-dateutil==2.8.2 python-dotenv==1.0.0 +python-multipart==0.0.6 +s3transfer==0.7.0 +six==1.16.0 sniffio==1.3.0 SQLAlchemy==1.4.49 starlette==0.27.0 tomlkit==0.12.1 typing_extensions==4.8.0 +urllib3==2.0.6 uvicorn==0.23.2