1er
This commit is contained in:
4
backend/app/api/__init__.py
Normal file
4
backend/app/api/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
"""Module routers."""
|
||||
from .routes_config import router as config_router
|
||||
from .routes_products import router as products_router
|
||||
from .routes_scrape import router as scrape_router
|
||||
13
backend/app/api/deps.py
Normal file
13
backend/app/api/deps.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from backend.app.db.database import SessionLocal
|
||||
|
||||
|
||||
def get_db() -> Session:
|
||||
db = SessionLocal()
|
||||
try:
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
28
backend/app/api/routes_config.py
Normal file
28
backend/app/api/routes_config.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import APIRouter, Body, HTTPException
|
||||
|
||||
from backend.app.core.config import BackendConfig, CONFIG_PATH, load_config
|
||||
|
||||
router = APIRouter(prefix="/config", tags=["config"])
|
||||
|
||||
|
||||
@router.get("/backend", response_model=BackendConfig)
|
||||
def read_backend_config() -> BackendConfig:
|
||||
# expose la configuration backend en lecture seule
|
||||
return load_config()
|
||||
|
||||
|
||||
@router.put("/backend", response_model=BackendConfig)
|
||||
def update_backend_config(payload: dict = Body(...)) -> BackendConfig:
|
||||
current = load_config()
|
||||
try:
|
||||
# validation via Pydantic avant écriture
|
||||
updated = current.copy(update=payload)
|
||||
CONFIG_PATH.write_text(updated.json(indent=2, ensure_ascii=False))
|
||||
load_config.cache_clear()
|
||||
return load_config()
|
||||
except Exception as exc: # pragma: no cover
|
||||
raise HTTPException(status_code=400, detail=str(exc))
|
||||
47
backend/app/api/routes_products.py
Normal file
47
backend/app/api/routes_products.py
Normal file
@@ -0,0 +1,47 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from backend.app.api.deps import get_db
|
||||
from backend.app.db import crud, schemas
|
||||
|
||||
router = APIRouter(prefix="/products", tags=["products"])
|
||||
|
||||
|
||||
@router.get("", response_model=list[schemas.ProductRead])
|
||||
def list_products(skip: int = 0, limit: int = 50, db: Session = Depends(get_db)) -> list[schemas.ProductRead]:
|
||||
# on retourne la liste paginée de produits
|
||||
return crud.list_products(db, skip=skip, limit=limit)
|
||||
|
||||
|
||||
@router.post("", response_model=schemas.ProductRead, status_code=status.HTTP_201_CREATED)
|
||||
def create_product(payload: schemas.ProductCreate, db: Session = Depends(get_db)) -> schemas.ProductRead:
|
||||
# création de produit rigoureuse via Pydantic
|
||||
return crud.create_product(db, payload)
|
||||
|
||||
|
||||
@router.get("/{product_id}", response_model=schemas.ProductRead)
|
||||
def read_product(product_id: int, db: Session = Depends(get_db)) -> schemas.ProductRead:
|
||||
product = crud.get_product(db, product_id)
|
||||
if not product:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Produit introuvable")
|
||||
return product
|
||||
|
||||
|
||||
@router.put("/{product_id}", response_model=schemas.ProductRead)
|
||||
def update_product(product_id: int, payload: schemas.ProductUpdate, db: Session = Depends(get_db)) -> schemas.ProductRead:
|
||||
product = crud.get_product(db, product_id)
|
||||
if not product:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Produit introuvable")
|
||||
# mise à jour partielle des champs éditables
|
||||
return crud.update_product(db, product, payload)
|
||||
|
||||
|
||||
@router.delete("/{product_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_product(product_id: int, db: Session = Depends(get_db)) -> None:
|
||||
product = crud.get_product(db, product_id)
|
||||
if not product:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Produit introuvable")
|
||||
# suppression définitive en base
|
||||
crud.remove_product(db, product)
|
||||
20
backend/app/api/routes_scrape.py
Normal file
20
backend/app/api/routes_scrape.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import APIRouter, BackgroundTasks
|
||||
|
||||
from backend.app.scraper.runner import scrape_all, scrape_product
|
||||
|
||||
router = APIRouter(prefix="/scrape", tags=["scrape"])
|
||||
|
||||
|
||||
@router.post("/product/{product_id}")
|
||||
def trigger_single(product_id: int, background_tasks: BackgroundTasks):
|
||||
# on délègue le vrai travail à un background task rapide
|
||||
background_tasks.add_task(scrape_product, product_id)
|
||||
return {"statut": "planifie", "cible": product_id}
|
||||
|
||||
|
||||
@router.post("/all")
|
||||
def trigger_all(background_tasks: BackgroundTasks):
|
||||
background_tasks.add_task(scrape_all)
|
||||
return {"statut": "planifie_tout"}
|
||||
Reference in New Issue
Block a user