new shems
This commit is contained in:
227
route/scale_crud.py
Normal file
227
route/scale_crud.py
Normal file
@@ -0,0 +1,227 @@
|
||||
"""
|
||||
CRUD для осей (ScaleDimension) и расшифровок вариантов ответов (ChoiceScore).
|
||||
|
||||
Эндпоинты:
|
||||
POST /polls/{poll_id}/dimensions — создать ось для теста
|
||||
GET /polls/{poll_id}/dimensions — список осей теста
|
||||
PUT /dimensions/{dimension_id} — изменить ось
|
||||
DELETE /dimensions/{dimension_id} — удалить ось
|
||||
|
||||
POST /dimensions/{dimension_id}/scores — задать расшифровку для варианта ответа
|
||||
GET /dimensions/{dimension_id}/scores — список расшифровок по оси
|
||||
GET /choices/{choice_id}/scores — расшифровки конкретного варианта
|
||||
DELETE /choice-scores/{score_id} — удалить расшифровку
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from typing import List, Optional
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
from bd import make_engine
|
||||
from bd.tables.poll import Poll
|
||||
from bd.tables.choice import Choice
|
||||
from bd.tables.scale import ScaleDimension, ChoiceScore
|
||||
|
||||
router = APIRouter(tags=["scale"])
|
||||
|
||||
|
||||
def get_session():
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
return sessionmaker(bind=make_engine(), future=True)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Схемы
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class DimensionIn(BaseModel):
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
color: Optional[str] = None
|
||||
position: Optional[int] = None
|
||||
|
||||
|
||||
class DimensionOut(BaseModel):
|
||||
id: str
|
||||
poll_id: str
|
||||
name: str
|
||||
description: Optional[str]
|
||||
color: Optional[str]
|
||||
position: Optional[int]
|
||||
|
||||
|
||||
class ChoiceScoreIn(BaseModel):
|
||||
choice_id: str
|
||||
score: float = 1.0
|
||||
|
||||
|
||||
class ChoiceScoreOut(BaseModel):
|
||||
id: str
|
||||
choice_id: str
|
||||
dimension_id: str
|
||||
score: float
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Оси (ScaleDimension)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@router.post("/polls/{poll_id}/dimensions", response_model=DimensionOut, status_code=201,
|
||||
tags=["scale"])
|
||||
def create_dimension(poll_id: str, payload: DimensionIn):
|
||||
Session = get_session()
|
||||
try:
|
||||
pid = uuid.UUID(poll_id)
|
||||
except Exception:
|
||||
raise HTTPException(status_code=400, detail="Invalid poll UUID")
|
||||
with Session() as session:
|
||||
if not session.get(Poll, pid):
|
||||
raise HTTPException(status_code=404, detail="Poll not found")
|
||||
dim = ScaleDimension(
|
||||
poll_id=pid,
|
||||
name=payload.name,
|
||||
description=payload.description,
|
||||
color=payload.color,
|
||||
position=payload.position,
|
||||
)
|
||||
session.add(dim)
|
||||
session.commit()
|
||||
session.refresh(dim)
|
||||
return DimensionOut(
|
||||
id=str(dim.id), poll_id=str(dim.poll_id),
|
||||
name=dim.name, description=dim.description,
|
||||
color=dim.color, position=dim.position,
|
||||
)
|
||||
|
||||
|
||||
@router.get("/polls/{poll_id}/dimensions", response_model=List[DimensionOut],
|
||||
tags=["scale"])
|
||||
def list_dimensions(poll_id: str):
|
||||
Session = get_session()
|
||||
try:
|
||||
pid = uuid.UUID(poll_id)
|
||||
except Exception:
|
||||
raise HTTPException(status_code=400, detail="Invalid poll UUID")
|
||||
with Session() as session:
|
||||
dims = (
|
||||
session.query(ScaleDimension)
|
||||
.filter(ScaleDimension.poll_id == pid)
|
||||
.order_by(ScaleDimension.position.asc().nullslast())
|
||||
.all()
|
||||
)
|
||||
return [
|
||||
DimensionOut(id=str(d.id), poll_id=str(d.poll_id),
|
||||
name=d.name, description=d.description,
|
||||
color=d.color, position=d.position)
|
||||
for d in dims
|
||||
]
|
||||
|
||||
|
||||
@router.put("/dimensions/{dimension_id}", response_model=DimensionOut, tags=["scale"])
|
||||
def update_dimension(dimension_id: str, payload: DimensionIn):
|
||||
Session = get_session()
|
||||
try:
|
||||
did = uuid.UUID(dimension_id)
|
||||
except Exception:
|
||||
raise HTTPException(status_code=400, detail="Invalid dimension UUID")
|
||||
with Session() as session:
|
||||
dim = session.get(ScaleDimension, did)
|
||||
if not dim:
|
||||
raise HTTPException(status_code=404, detail="Dimension not found")
|
||||
dim.name = payload.name
|
||||
dim.description = payload.description
|
||||
dim.color = payload.color
|
||||
dim.position = payload.position
|
||||
session.commit()
|
||||
session.refresh(dim)
|
||||
return DimensionOut(id=str(dim.id), poll_id=str(dim.poll_id),
|
||||
name=dim.name, description=dim.description,
|
||||
color=dim.color, position=dim.position)
|
||||
|
||||
|
||||
@router.delete("/dimensions/{dimension_id}", status_code=204, tags=["scale"])
|
||||
def delete_dimension(dimension_id: str):
|
||||
Session = get_session()
|
||||
try:
|
||||
did = uuid.UUID(dimension_id)
|
||||
except Exception:
|
||||
raise HTTPException(status_code=400, detail="Invalid dimension UUID")
|
||||
with Session() as session:
|
||||
dim = session.get(ScaleDimension, did)
|
||||
if not dim:
|
||||
raise HTTPException(status_code=404, detail="Dimension not found")
|
||||
session.delete(dim)
|
||||
session.commit()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Расшифровки вариантов ответов (ChoiceScore)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@router.post("/dimensions/{dimension_id}/scores", response_model=ChoiceScoreOut,
|
||||
status_code=201, tags=["scale"])
|
||||
def create_choice_score(dimension_id: str, payload: ChoiceScoreIn):
|
||||
Session = get_session()
|
||||
try:
|
||||
did = uuid.UUID(dimension_id)
|
||||
cid = uuid.UUID(payload.choice_id)
|
||||
except Exception:
|
||||
raise HTTPException(status_code=400, detail="Invalid UUID")
|
||||
with Session() as session:
|
||||
if not session.get(ScaleDimension, did):
|
||||
raise HTTPException(status_code=404, detail="Dimension not found")
|
||||
if not session.get(Choice, cid):
|
||||
raise HTTPException(status_code=404, detail="Choice not found")
|
||||
cs = ChoiceScore(choice_id=cid, dimension_id=did, score=payload.score)
|
||||
session.add(cs)
|
||||
session.commit()
|
||||
session.refresh(cs)
|
||||
return ChoiceScoreOut(id=str(cs.id), choice_id=str(cs.choice_id),
|
||||
dimension_id=str(cs.dimension_id), score=cs.score)
|
||||
|
||||
|
||||
@router.get("/dimensions/{dimension_id}/scores", response_model=List[ChoiceScoreOut],
|
||||
tags=["scale"])
|
||||
def list_scores_by_dimension(dimension_id: str):
|
||||
Session = get_session()
|
||||
try:
|
||||
did = uuid.UUID(dimension_id)
|
||||
except Exception:
|
||||
raise HTTPException(status_code=400, detail="Invalid dimension UUID")
|
||||
with Session() as session:
|
||||
rows = session.query(ChoiceScore).filter(ChoiceScore.dimension_id == did).all()
|
||||
return [ChoiceScoreOut(id=str(r.id), choice_id=str(r.choice_id),
|
||||
dimension_id=str(r.dimension_id), score=r.score)
|
||||
for r in rows]
|
||||
|
||||
|
||||
@router.get("/choices/{choice_id}/scores", response_model=List[ChoiceScoreOut],
|
||||
tags=["scale"])
|
||||
def list_scores_by_choice(choice_id: str):
|
||||
Session = get_session()
|
||||
try:
|
||||
cid = uuid.UUID(choice_id)
|
||||
except Exception:
|
||||
raise HTTPException(status_code=400, detail="Invalid choice UUID")
|
||||
with Session() as session:
|
||||
rows = session.query(ChoiceScore).filter(ChoiceScore.choice_id == cid).all()
|
||||
return [ChoiceScoreOut(id=str(r.id), choice_id=str(r.choice_id),
|
||||
dimension_id=str(r.dimension_id), score=r.score)
|
||||
for r in rows]
|
||||
|
||||
|
||||
@router.delete("/choice-scores/{score_id}", status_code=204, tags=["scale"])
|
||||
def delete_choice_score(score_id: str):
|
||||
Session = get_session()
|
||||
try:
|
||||
sid = uuid.UUID(score_id)
|
||||
except Exception:
|
||||
raise HTTPException(status_code=400, detail="Invalid UUID")
|
||||
with Session() as session:
|
||||
cs = session.get(ChoiceScore, sid)
|
||||
if not cs:
|
||||
raise HTTPException(status_code=404, detail="Score not found")
|
||||
session.delete(cs)
|
||||
session.commit()
|
||||
Reference in New Issue
Block a user