♻ Refactor items and services endpoints to return count and data, and add CI tests (#599)
Co-authored-by: Esteban Maya Cadavid <emaya@trueblue.com> Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from sqlmodel import select
|
||||
from sqlmodel import select, func
|
||||
|
||||
from app.api.deps import CurrentUser, SessionDep
|
||||
from app.models import Item, ItemCreate, ItemOut, ItemUpdate, Message
|
||||
from app.models import Item, ItemCreate, ItemOut, ItemUpdate, Message, ItemsOut
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/", response_model=list[ItemOut])
|
||||
@router.get("/", response_model=ItemsOut)
|
||||
def read_items(
|
||||
session: SessionDep, current_user: CurrentUser, skip: int = 0, limit: int = 100
|
||||
) -> Any:
|
||||
@@ -17,9 +17,12 @@ def read_items(
|
||||
Retrieve items.
|
||||
"""
|
||||
|
||||
statment = select(func.count()).select_from(Item)
|
||||
count = session.exec(statment).one()
|
||||
|
||||
if current_user.is_superuser:
|
||||
statement = select(Item).offset(skip).limit(limit)
|
||||
return session.exec(statement).all()
|
||||
items = session.exec(statement).all()
|
||||
else:
|
||||
statement = (
|
||||
select(Item)
|
||||
@@ -27,7 +30,9 @@ def read_items(
|
||||
.offset(skip)
|
||||
.limit(limit)
|
||||
)
|
||||
return session.exec(statement).all()
|
||||
items = session.exec(statement).all()
|
||||
|
||||
return ItemsOut(data=items, count=count)
|
||||
|
||||
|
||||
@router.get("/{id}", response_model=ItemOut)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
from typing import Any, List
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlmodel import select
|
||||
from sqlmodel import select, func
|
||||
|
||||
from app import crud
|
||||
from app.api.deps import (
|
||||
@@ -18,6 +18,7 @@ from app.models import (
|
||||
UserCreate,
|
||||
UserCreateOpen,
|
||||
UserOut,
|
||||
UsersOut,
|
||||
UserUpdate,
|
||||
UserUpdateMe,
|
||||
)
|
||||
@@ -29,15 +30,20 @@ router = APIRouter()
|
||||
@router.get(
|
||||
"/",
|
||||
dependencies=[Depends(get_current_active_superuser)],
|
||||
response_model=List[UserOut],
|
||||
response_model=UsersOut
|
||||
)
|
||||
def read_users(session: SessionDep, skip: int = 0, limit: int = 100) -> Any:
|
||||
"""
|
||||
Retrieve users.
|
||||
"""
|
||||
|
||||
statment = select(func.count()).select_from(User)
|
||||
count = session.exec(statment).one()
|
||||
|
||||
statement = select(User).offset(skip).limit(limit)
|
||||
users = session.exec(statement).all()
|
||||
return users
|
||||
|
||||
return UsersOut(data=users, count=count)
|
||||
|
||||
|
||||
@router.post(
|
||||
|
@@ -51,6 +51,11 @@ class UserOut(UserBase):
|
||||
id: int
|
||||
|
||||
|
||||
class UsersOut(SQLModel):
|
||||
data: list[UserOut]
|
||||
count: int
|
||||
|
||||
|
||||
# Shared properties
|
||||
class ItemBase(SQLModel):
|
||||
title: str
|
||||
@@ -80,6 +85,12 @@ class Item(ItemBase, table=True):
|
||||
# Properties to return via API, id is always required
|
||||
class ItemOut(ItemBase):
|
||||
id: int
|
||||
owner_id: int
|
||||
|
||||
|
||||
class ItemsOut(SQLModel):
|
||||
data: list[ItemOut]
|
||||
count: int
|
||||
|
||||
|
||||
# Generic message
|
||||
|
@@ -8,11 +8,11 @@ from app.core.config import settings
|
||||
def test_celery_worker_test(
|
||||
client: TestClient, superuser_token_headers: Dict[str, str]
|
||||
) -> None:
|
||||
data = {"msg": "test"}
|
||||
data = {"message": "test"}
|
||||
r = client.post(
|
||||
f"{settings.API_V1_STR}/utils/test-celery/",
|
||||
json=data,
|
||||
headers=superuser_token_headers,
|
||||
)
|
||||
response = r.json()
|
||||
assert response["msg"] == "Word received"
|
||||
assert response["message"] == "Word received"
|
||||
|
@@ -110,6 +110,7 @@ def test_retrieve_users(
|
||||
r = client.get(f"{settings.API_V1_STR}/users/", headers=superuser_token_headers)
|
||||
all_users = r.json()
|
||||
|
||||
assert len(all_users) > 1
|
||||
for item in all_users:
|
||||
assert len(all_users["data"]) > 1
|
||||
assert "count" in all_users
|
||||
for item in all_users["data"]:
|
||||
assert "email" in item
|
||||
|
@@ -23,6 +23,8 @@ python-jose = {extras = ["cryptography"], version = "^3.3.0"}
|
||||
httpx = "^0.25.1"
|
||||
psycopg = {extras = ["binary"], version = "^3.1.13"}
|
||||
sqlmodel = "^0.0.16"
|
||||
# Pin bcrypt until passlib supports the latest
|
||||
bcrypt = "4.0.1"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
mypy = "^1.7.0"
|
||||
|
@@ -28,10 +28,22 @@ services:
|
||||
- traefik.http.routers.${STACK_NAME?Variable not set}-traefik-public-http.rule=Host(`${DOMAIN?Variable not set}`)
|
||||
- traefik.http.services.${STACK_NAME?Variable not set}-traefik-public.loadbalancer.server.port=80
|
||||
|
||||
db:
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
pgadmin:
|
||||
ports:
|
||||
- "5050:5050"
|
||||
|
||||
# Uncomment the section below to be able to debug locally
|
||||
# queue:
|
||||
# ports:
|
||||
# - "5671:5671"
|
||||
# - "5672:5672"
|
||||
# - "15672:15672"
|
||||
# - "15671:15671"
|
||||
|
||||
flower:
|
||||
ports:
|
||||
- "5555:5555"
|
||||
@@ -84,14 +96,14 @@ services:
|
||||
- traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.rule=Host(`old-frontend.localhost.tiangolo.com`)
|
||||
- traefik.http.services.${STACK_NAME?Variable not set}-frontend.loadbalancer.server.port=80
|
||||
|
||||
new-frontend:
|
||||
build:
|
||||
context: ./new-frontend
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set}
|
||||
- traefik.http.routers.${STACK_NAME?Variable not set}-new-frontend-http.rule=PathPrefix(`/`)
|
||||
- traefik.http.services.${STACK_NAME?Variable not set}-new-frontend.loadbalancer.server.port=80
|
||||
# new-frontend:
|
||||
# build:
|
||||
# context: ./new-frontend
|
||||
# labels:
|
||||
# - traefik.enable=true
|
||||
# - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set}
|
||||
# - traefik.http.routers.${STACK_NAME?Variable not set}-new-frontend-http.rule=PathPrefix(`/`)
|
||||
# - traefik.http.services.${STACK_NAME?Variable not set}-new-frontend.loadbalancer.server.port=80
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
|
@@ -191,16 +191,16 @@ services:
|
||||
- traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.rule=PathPrefix(`/`)
|
||||
- traefik.http.services.${STACK_NAME?Variable not set}-frontend.loadbalancer.server.port=80
|
||||
|
||||
new-frontend:
|
||||
image: '${DOCKER_IMAGE_NEW_FRONTEND?Variable not set}:${TAG-latest}'
|
||||
build:
|
||||
context: ./new-frontend
|
||||
deploy:
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set}
|
||||
- traefik.http.routers.${STACK_NAME?Variable not set}-new-frontend-http.rule=PathPrefix(`/`)
|
||||
- traefik.http.services.${STACK_NAME?Variable not set}-new-frontend.loadbalancer.server.port=80
|
||||
# new-frontend:
|
||||
# image: '${DOCKER_IMAGE_NEW_FRONTEND?Variable not set}:${TAG-latest}'
|
||||
# build:
|
||||
# context: ./new-frontend
|
||||
# deploy:
|
||||
# labels:
|
||||
# - traefik.enable=true
|
||||
# - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set}
|
||||
# - traefik.http.routers.${STACK_NAME?Variable not set}-new-frontend-http.rule=PathPrefix(`/`)
|
||||
# - traefik.http.services.${STACK_NAME?Variable not set}-new-frontend.loadbalancer.server.port=80
|
||||
|
||||
|
||||
volumes:
|
||||
|
Reference in New Issue
Block a user