Compare commits
2 Commits
e328fd4100
...
821741a9f8
Author | SHA1 | Date | |
---|---|---|---|
821741a9f8 | |||
81d71e60f5 |
49
crud.py
49
crud.py
@ -1,5 +1,5 @@
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from models import Car, EngineType, HybridType, PowerRatio
|
from models import Car, EngineType, HybridType, PowerRatio, Personal
|
||||||
import schemas
|
import schemas
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
@ -72,3 +72,50 @@ def delete_car(db: Session, car_id: int) -> bool:
|
|||||||
db.delete(db_car)
|
db.delete(db_car)
|
||||||
db.commit()
|
db.commit()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# Персонал ---------
|
||||||
|
|
||||||
|
def get_personal(db: Session, personal_id: int) -> Optional[Personal]:
|
||||||
|
return db.query(Personal).filter(Personal.id == personal_id).first()
|
||||||
|
|
||||||
|
def get_all_personal(db: Session, skip: int = 0, limit: int = 100) -> List[Personal]:
|
||||||
|
return db.query(Personal).offset(skip).limit(limit).all()
|
||||||
|
|
||||||
|
def get_personal_count(db: Session) -> int:
|
||||||
|
return db.query(Personal).count()
|
||||||
|
|
||||||
|
def create_personal(db: Session, personal: schemas.PersonalCreate) -> Personal:
|
||||||
|
db_personal = Personal(
|
||||||
|
name=personal.name,
|
||||||
|
surname=personal.surname,
|
||||||
|
role=personal.role,
|
||||||
|
photo=personal.photo
|
||||||
|
)
|
||||||
|
db.add(db_personal)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_personal)
|
||||||
|
return db_personal
|
||||||
|
|
||||||
|
def update_personal(db: Session, personal_id: int, personal_update: schemas.PersonalUpdate) -> Optional[Personal]:
|
||||||
|
db_personal = get_personal(db, personal_id)
|
||||||
|
if not db_personal:
|
||||||
|
return None
|
||||||
|
|
||||||
|
update_data = personal_update.model_dump(exclude_unset=True)
|
||||||
|
|
||||||
|
# Обновление полей
|
||||||
|
for key, value in update_data.items():
|
||||||
|
setattr(db_personal, key, value)
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_personal)
|
||||||
|
return db_personal
|
||||||
|
|
||||||
|
def delete_personal(db: Session, personal_id: int) -> bool:
|
||||||
|
db_personal = get_personal(db, personal_id)
|
||||||
|
if not db_personal:
|
||||||
|
return False
|
||||||
|
|
||||||
|
db.delete(db_personal)
|
||||||
|
db.commit()
|
||||||
|
return True
|
135
main.py
135
main.py
@ -9,12 +9,21 @@ from typing import List, Optional
|
|||||||
import uvicorn
|
import uvicorn
|
||||||
from utils import save_image, delete_image
|
from utils import save_image, delete_image
|
||||||
import json
|
import json
|
||||||
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
|
||||||
# Создание таблиц в БД
|
# Создание таблиц в БД
|
||||||
models.Base.metadata.create_all(bind=engine)
|
models.Base.metadata.create_all(bind=engine)
|
||||||
|
|
||||||
app = FastAPI(title="AutoBro API", description="API для управления базой данных автомобилей")
|
app = FastAPI(title="AutoBro API", description="API для управления базой данных автомобилей")
|
||||||
|
|
||||||
|
app.add_middleware(
|
||||||
|
CORSMiddleware,
|
||||||
|
allow_origins=["*"],
|
||||||
|
allow_credentials=True,
|
||||||
|
allow_methods=["*"],
|
||||||
|
allow_headers=["*",]
|
||||||
|
)
|
||||||
|
|
||||||
# Добавляем обработку статических файлов
|
# Добавляем обработку статических файлов
|
||||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||||
|
|
||||||
@ -148,3 +157,129 @@ def delete_car(
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
uvicorn.run(app, host="0.0.0.0", port=3000)
|
uvicorn.run(app, host="0.0.0.0", port=3000)
|
||||||
|
|
||||||
|
# Персонал ---------
|
||||||
|
|
||||||
|
@app.get("/personal", response_model=schemas.PersonalListResponse)
|
||||||
|
def get_all_personal(
|
||||||
|
skip: int = Query(0, description="Количество пропускаемых записей"),
|
||||||
|
limit: int = Query(100, description="Максимальное количество записей"),
|
||||||
|
db: Session = Depends(get_db)
|
||||||
|
):
|
||||||
|
staff = crud.get_all_personal(db, skip=skip, limit=limit)
|
||||||
|
total = crud.get_personal_count(db)
|
||||||
|
return {"staff": staff, "total": total}
|
||||||
|
|
||||||
|
@app.get("/personal/{personal_id}", response_model=schemas.PersonalResponse)
|
||||||
|
def get_personal(
|
||||||
|
personal_id: int = Path(..., description="ID сотрудника", gt=0),
|
||||||
|
db: Session = Depends(get_db)
|
||||||
|
):
|
||||||
|
personal = crud.get_personal(db, personal_id=personal_id)
|
||||||
|
if personal is None:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="Сотрудник не найден"
|
||||||
|
)
|
||||||
|
return {"personal": personal}
|
||||||
|
|
||||||
|
@app.post("/personal", response_model=schemas.PersonalResponse, status_code=status.HTTP_201_CREATED)
|
||||||
|
async def create_personal(
|
||||||
|
personal_data: str = Form(..., description="Данные сотрудника в JSON формате"),
|
||||||
|
photo: UploadFile = File(None, description="Фотография сотрудника"),
|
||||||
|
db: Session = Depends(get_db)
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
# Преобразуем строку JSON в словарь
|
||||||
|
personal_dict = json.loads(personal_data)
|
||||||
|
|
||||||
|
# Загружаем фото, если оно предоставлено
|
||||||
|
if photo:
|
||||||
|
photo_path = await save_image(photo)
|
||||||
|
personal_dict["photo"] = photo_path
|
||||||
|
|
||||||
|
# Создаем объект Pydantic для валидации данных
|
||||||
|
personal = schemas.PersonalCreate(**personal_dict)
|
||||||
|
|
||||||
|
# Создаем запись в БД
|
||||||
|
db_personal = crud.create_personal(db=db, personal=personal)
|
||||||
|
return {"personal": db_personal}
|
||||||
|
except ValueError as e:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=str(e)
|
||||||
|
)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="Неверный формат JSON"
|
||||||
|
)
|
||||||
|
|
||||||
|
@app.put("/personal/{personal_id}", response_model=schemas.PersonalResponse)
|
||||||
|
async def update_personal(
|
||||||
|
personal_id: int = Path(..., description="ID сотрудника", gt=0),
|
||||||
|
personal_data: str = Form(None, description="Данные сотрудника в JSON формате"),
|
||||||
|
photo: UploadFile = File(None, description="Фотография сотрудника"),
|
||||||
|
db: Session = Depends(get_db)
|
||||||
|
):
|
||||||
|
# Проверяем существование сотрудника
|
||||||
|
existing_personal = crud.get_personal(db, personal_id=personal_id)
|
||||||
|
if existing_personal is None:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="Сотрудник не найден"
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Преобразуем строку JSON в словарь, если она предоставлена
|
||||||
|
personal_dict = {}
|
||||||
|
if personal_data:
|
||||||
|
personal_dict = json.loads(personal_data)
|
||||||
|
|
||||||
|
# Загружаем новую фотографию, если она предоставлена
|
||||||
|
if photo:
|
||||||
|
# Удаляем старую фотографию, если есть
|
||||||
|
if existing_personal.photo:
|
||||||
|
delete_image(existing_personal.photo)
|
||||||
|
|
||||||
|
# Сохраняем новую фотографию
|
||||||
|
photo_path = await save_image(photo)
|
||||||
|
personal_dict["photo"] = photo_path
|
||||||
|
|
||||||
|
# Создаем объект Pydantic для валидации данных
|
||||||
|
personal_update = schemas.PersonalUpdate(**personal_dict)
|
||||||
|
|
||||||
|
# Обновляем запись в БД
|
||||||
|
updated_personal = crud.update_personal(db=db, personal_id=personal_id, personal_update=personal_update)
|
||||||
|
return {"personal": updated_personal}
|
||||||
|
except ValueError as e:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=str(e)
|
||||||
|
)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="Неверный формат JSON"
|
||||||
|
)
|
||||||
|
|
||||||
|
@app.delete("/personal/{personal_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||||
|
def delete_personal(
|
||||||
|
personal_id: int = Path(..., description="ID сотрудника", gt=0),
|
||||||
|
db: Session = Depends(get_db)
|
||||||
|
):
|
||||||
|
# Получаем сотрудника перед удалением
|
||||||
|
personal = crud.get_personal(db, personal_id=personal_id)
|
||||||
|
if personal is None:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="Сотрудник не найден"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Удаляем фотографию, если есть
|
||||||
|
if personal.photo:
|
||||||
|
delete_image(personal.photo)
|
||||||
|
|
||||||
|
# Удаляем запись из БД
|
||||||
|
crud.delete_personal(db=db, personal_id=personal_id)
|
||||||
|
return None
|
||||||
|
@ -35,3 +35,12 @@ class Car(Base):
|
|||||||
electric_motor_power = Column(Integer, nullable=True) # мощность электродвигателя
|
electric_motor_power = Column(Integer, nullable=True) # мощность электродвигателя
|
||||||
hybrid_type = Column(Enum(HybridType), default=HybridType.NONE) # тип гибрида
|
hybrid_type = Column(Enum(HybridType), default=HybridType.NONE) # тип гибрида
|
||||||
power_ratio = Column(Enum(PowerRatio), default=PowerRatio.NA) # соотношение мощности
|
power_ratio = Column(Enum(PowerRatio), default=PowerRatio.NA) # соотношение мощности
|
||||||
|
|
||||||
|
class Personal(Base):
|
||||||
|
__tablename__ = "personal"
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True, index=True)
|
||||||
|
name = Column(String, index=True) # ФИО сотрудника
|
||||||
|
surname = Column(String, index=True) # ФИО сотрудника
|
||||||
|
role = Column(String) # Должность (произвольная строка)
|
||||||
|
photo = Column(String, nullable=True) # путь к фотографии
|
||||||
|
30
schemas.py
30
schemas.py
@ -65,3 +65,33 @@ class CarResponse(BaseModel):
|
|||||||
class CarsResponse(BaseModel):
|
class CarsResponse(BaseModel):
|
||||||
cars: List[Car]
|
cars: List[Car]
|
||||||
total: int
|
total: int
|
||||||
|
|
||||||
|
# Персонал ---------
|
||||||
|
|
||||||
|
class PersonalBase(BaseModel):
|
||||||
|
name: str
|
||||||
|
surname: str
|
||||||
|
role: str
|
||||||
|
photo: Optional[str] = None
|
||||||
|
|
||||||
|
class PersonalCreate(PersonalBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class PersonalUpdate(BaseModel):
|
||||||
|
name: Optional[str] = None
|
||||||
|
surname: Optional[str] = None
|
||||||
|
role: Optional[str] = None
|
||||||
|
photo: Optional[str] = None
|
||||||
|
|
||||||
|
class Personal(PersonalBase):
|
||||||
|
id: int
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
from_attributes = True
|
||||||
|
|
||||||
|
class PersonalResponse(BaseModel):
|
||||||
|
personal: Personal
|
||||||
|
|
||||||
|
class PersonalListResponse(BaseModel):
|
||||||
|
staff: List[Personal]
|
||||||
|
total: int
|
Reference in New Issue
Block a user