Преглед на файлове

init router, config, crud, db_base, db_session, models, schemas for database

chenhaiyang преди 4 години
родител
ревизия
37edc9a468
променени са 15 файла, в които са добавени 223 реда и са изтрити 8 реда
  1. 1 1
      alembic.ini
  2. 11 0
      app/api/dependencies/db.py
  3. 35 0
      app/api/routers/item.py
  4. 0 5
      app/core/config.py
  5. 9 0
      app/crud/__init__.py
  6. 66 0
      app/crud/base.py
  7. 30 0
      app/crud/crud_item.py
  8. 4 0
      app/db/base.py
  9. 14 0
      app/db/base_class.py
  10. 7 0
      app/db/session.py
  11. 3 2
      app/main.py
  12. 1 0
      app/models/__init__.py
  13. 9 0
      app/models/item.py
  14. 1 0
      app/schemas/__init__.py
  15. 32 0
      app/schemas/item.py

+ 1 - 1
alembic.ini

@@ -35,7 +35,7 @@ script_location = alembic
 # are written from script.py.mako
 # are written from script.py.mako
 # output_encoding = utf-8
 # output_encoding = utf-8
 
 
-sqlalchemy.url = driver://user:pass@localhost/dbname
+# sqlalchemy.url = driver://user:pass@localhost/dbname
 
 
 
 
 [post_write_hooks]
 [post_write_hooks]

+ 11 - 0
app/api/dependencies/db.py

@@ -0,0 +1,11 @@
+from typing import Generator
+
+from app.db.session import SessionLocal
+
+
+def get_db() -> Generator:
+    db = SessionLocal()
+    try:
+        yield db
+    finally:
+        db.close()

+ 35 - 0
app/api/routers/item.py

@@ -0,0 +1,35 @@
+from typing import Any, List
+
+from fastapi import APIRouter, Depends
+from sqlalchemy.orm import Session
+
+from app import crud, schemas
+from app.api.dependencies.db import get_db
+
+router = APIRouter()
+
+
+@router.get("/", response_model=List[schemas.Item])
+def read_items(
+        db: Session = Depends(get_db),
+        skip: int = 0,
+        limit: int = 100,
+) -> Any:
+    """
+    Retrieve items.
+    """
+    items = crud.item.get_multi(db, skip=skip, limit=limit)
+    return items
+
+
+@router.post("/", response_model=schemas.Item)
+def create_item(
+        *,
+        db: Session = Depends(get_db),
+        item_in: schemas.ItemCreate,
+) -> Any:
+    """
+    Create new item.
+    """
+    item = crud.item.create_with_owner(db=db, obj_in=item_in)
+    return item

+ 0 - 5
app/core/config.py

@@ -1,16 +1,11 @@
 # -*- coding: utf-8 -*-
 # -*- coding: utf-8 -*-
 
 
-import secrets
 from typing import Any, Dict, Optional
 from typing import Any, Dict, Optional
 
 
 from pydantic import AnyHttpUrl, BaseSettings, DirectoryPath, PostgresDsn, SecretStr, validator
 from pydantic import AnyHttpUrl, BaseSettings, DirectoryPath, PostgresDsn, SecretStr, validator
 
 
 
 
 class Settings(BaseSettings):
 class Settings(BaseSettings):
-    API_V1_STR: str = '/api/v1'
-    SECRET_KEY: str = secrets.token_urlsafe(32)
-    # 60 minutes * 24 hours * 8 days = 8 days
-    ACCESS_TOKEN_MINUTES: int = 60 * 24 * 8
     # SERVER_NAME: str
     # SERVER_NAME: str
     # SERVER_HOST: AnyHttpUrl
     # SERVER_HOST: AnyHttpUrl
 
 

+ 9 - 0
app/crud/__init__.py

@@ -0,0 +1,9 @@
+from .crud_item import item
+
+# For a new basic set of CRUD operations you could just do
+
+# from .base import CRUDBase
+# from app.models.item import Item
+# from app.schemas.item import ItemCreate, ItemUpdate
+
+# item = CRUDBase[Item, ItemCreate, ItemUpdate](Item)

+ 66 - 0
app/crud/base.py

@@ -0,0 +1,66 @@
+from typing import Any, Dict, Generic, List, Optional, Type, TypeVar, Union
+
+from fastapi.encoders import jsonable_encoder
+from pydantic import BaseModel
+from sqlalchemy.orm import Session
+
+from app.db.base_class import Base
+
+ModelType = TypeVar("ModelType", bound=Base)
+CreateSchemaType = TypeVar("CreateSchemaType", bound=BaseModel)
+UpdateSchemaType = TypeVar("UpdateSchemaType", bound=BaseModel)
+
+
+class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
+    def __init__(self, model: Type[ModelType]):
+        """
+        CRUD object with default methods to Create, Read, Update, Delete (CRUD).
+
+        **Parameters**
+
+        * `model`: A SQLAlchemy model class
+        * `schema`: A Pydantic model (schema) class
+        """
+        self.model = model
+
+    def get(self, db: Session, id: Any) -> Optional[ModelType]:
+        return db.query(self.model).filter(self.model.id == id).first()
+
+    def get_multi(
+            self, db: Session, *, skip: int = 0, limit: int = 100
+    ) -> List[ModelType]:
+        return db.query(self.model).offset(skip).limit(limit).all()
+
+    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
+        db.add(db_obj)
+        db.commit()
+        db.refresh(db_obj)
+        return db_obj
+
+    def update(
+            self,
+            db: Session,
+            *,
+            db_obj: ModelType,
+            obj_in: Union[UpdateSchemaType, Dict[str, Any]]
+    ) -> ModelType:
+        obj_data = jsonable_encoder(db_obj)
+        if isinstance(obj_in, dict):
+            update_data = obj_in
+        else:
+            update_data = obj_in.dict(exclude_unset=True)
+        for field in obj_data:
+            if field in update_data:
+                setattr(db_obj, field, update_data[field])
+        db.add(db_obj)
+        db.commit()
+        db.refresh(db_obj)
+        return db_obj
+
+    def remove(self, db: Session, *, id: int) -> ModelType:
+        obj = db.query(self.model).get(id)
+        db.delete(obj)
+        db.commit()
+        return obj

+ 30 - 0
app/crud/crud_item.py

@@ -0,0 +1,30 @@
+from typing import List
+
+from fastapi.encoders import jsonable_encoder
+from sqlalchemy.orm import Session
+
+from app.crud.base import CRUDBase
+from app.models.item import Item
+from app.schemas.item import ItemCreate, ItemUpdate
+
+
+class CRUDItem(CRUDBase[Item, ItemCreate, ItemUpdate]):
+    def create_with_owner(
+            self, db: Session, *, obj_in: ItemCreate
+    ) -> Item:
+        obj_in_data = jsonable_encoder(obj_in)
+        db_obj = self.model(**obj_in_data)
+        db.add(db_obj)
+        db.commit()
+        db.refresh(db_obj)
+        return db_obj
+
+    def get_multi_by_owner(
+            self, db: Session, *, owner_id: int, skip: int = 0, limit: int = 100
+    ) -> List[Item]:
+        return (
+            db.query(self.model).filter(Item.owner_id == owner_id).offset(skip).limit(limit).all()
+        )
+
+
+item = CRUDItem(Item)

+ 4 - 0
app/db/base.py

@@ -0,0 +1,4 @@
+# Import all the models, so that Base has them before being
+# imported by Alembic
+from app.db.base_class import Base  # noqa
+from app.models.item import Item  # noqa

+ 14 - 0
app/db/base_class.py

@@ -0,0 +1,14 @@
+from typing import Any
+
+from sqlalchemy.ext.declarative import as_declarative, declared_attr
+
+
+@as_declarative()
+class Base:
+    id: Any
+    __name__: str
+    # Generate __tablename__ automatically
+
+    @declared_attr
+    def __tablename__(self) -> str:
+        return self.__name__.lower()

+ 7 - 0
app/db/session.py

@@ -0,0 +1,7 @@
+from sqlalchemy import create_engine
+from sqlalchemy.orm import sessionmaker
+
+from app.core.config import settings
+
+engine = create_engine(settings.SQLALCHEMY_DATABASE_URI, pool_pre_ping=True)
+SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

+ 3 - 2
app/main.py

@@ -7,18 +7,19 @@ import uvicorn
 from fastapi import FastAPI
 from fastapi import FastAPI
 from loguru import logger
 from loguru import logger
 
 
-from app.api.routers import targets, equipment, space
+from app.api.routers import targets, equipment, space, item
 from app.core.config import settings
 from app.core.config import settings
 from app.core.logger import InterceptHandler
 from app.core.logger import InterceptHandler
 
 
 logging.getLogger().handlers = [InterceptHandler()]
 logging.getLogger().handlers = [InterceptHandler()]
 logger.add(Path(settings.LOGS_DIR, 'env_fastapi.log'), level='INFO', rotation='00:00', encoding='utf-8')
 logger.add(Path(settings.LOGS_DIR, 'env_fastapi.log'), level='INFO', rotation='00:00', encoding='utf-8')
 
 
-app = FastAPI()
+app = FastAPI(title=settings.PROJECT_NAME)
 
 
 app.include_router(targets.router, prefix='/target')
 app.include_router(targets.router, prefix='/target')
 app.include_router(space.router, prefix='/room')
 app.include_router(space.router, prefix='/room')
 app.include_router(equipment.router, prefix='/equip')
 app.include_router(equipment.router, prefix='/equip')
+app.include_router(item.router, prefix='/item', tags=['items'])
 
 
 
 
 @app.get('/settings')
 @app.get('/settings')

+ 1 - 0
app/models/__init__.py

@@ -0,0 +1 @@
+from .item import Item

+ 9 - 0
app/models/item.py

@@ -0,0 +1,9 @@
+from sqlalchemy import Column, Integer, String
+
+from app.db.base_class import Base
+
+
+class Item(Base):
+    id = Column(Integer, primary_key=True, index=True)
+    title = Column(String, index=True)
+    description = Column(String, index=True)

+ 1 - 0
app/schemas/__init__.py

@@ -0,0 +1 @@
+from .item import Item, ItemCreate, ItemInDB, ItemUpdate

+ 32 - 0
app/schemas/item.py

@@ -0,0 +1,32 @@
+from typing import Optional
+
+from pydantic import BaseModel
+
+
+class ItemBase(BaseModel):
+    id: int
+    title: Optional[str] = None
+    description: Optional[str] = None
+
+
+class ItemCreate(ItemBase):
+    title: str
+
+
+class ItemUpdate(ItemBase):
+    pass
+
+
+class ItemInDBBase(ItemBase):
+    id: int
+
+    class Config:
+        orm_mode = True
+
+
+class Item(ItemInDBBase):
+    pass
+
+
+class ItemInDB(ItemInDBBase):
+    pass