94 lines
2.6 KiB
Python
94 lines
2.6 KiB
Python
from typing import Optional
|
|
from ninja import Router, Schema
|
|
from django.db.models import Count
|
|
from django.shortcuts import get_object_or_404
|
|
from .models import Category, Product
|
|
|
|
router = Router()
|
|
|
|
class CategoryOut(Schema):
|
|
id: int
|
|
name: str
|
|
product_count: int
|
|
|
|
class ImageInfo(Schema):
|
|
url: str
|
|
alt: str
|
|
|
|
class ProductListOut(Schema):
|
|
id: int
|
|
name: str
|
|
sku: Optional[str] = None
|
|
briefdesc: str
|
|
price: float
|
|
price_with_vat: float
|
|
stock: int
|
|
category_id: int
|
|
category_name: str
|
|
primary_image: Optional[ImageInfo] = None
|
|
average_rating: float
|
|
reviews_count: int
|
|
|
|
class ProductDetailOut(ProductListOut):
|
|
description: str
|
|
secondary_images: list[ImageInfo]
|
|
|
|
|
|
def _image_info(img, request):
|
|
if not img:
|
|
return None
|
|
return ImageInfo(
|
|
url=request.build_absolute_uri(img.image.url),
|
|
alt=img.alt or img.name,
|
|
)
|
|
|
|
def _product_to_list_out(p, request):
|
|
return ProductListOut(
|
|
id=p.id,
|
|
name=p.name,
|
|
sku=p.sku,
|
|
briefdesc=p.briefdesc,
|
|
price=p.price,
|
|
price_with_vat=p.get_price_with_vat(),
|
|
stock=p.stock,
|
|
category_id=p.category_id,
|
|
category_name=p.category.name,
|
|
primary_image=_image_info(p.primary_image, request),
|
|
average_rating=p.get_average_rating(),
|
|
reviews_count=p.get_reviews_count(),
|
|
)
|
|
|
|
def _product_to_detail_out(p, request):
|
|
base = _product_to_list_out(p, request)
|
|
data = base.dict()
|
|
data["description"] = p.description
|
|
data["secondary_images"] = [
|
|
_image_info(img, request) for img in p.secondary_images.all()
|
|
]
|
|
return ProductDetailOut(**data)
|
|
|
|
|
|
@router.get("/categorias", response=list[CategoryOut])
|
|
def listar_categorias(request):
|
|
qs = Category.objects.annotate(product_count=Count("product"))
|
|
return [
|
|
CategoryOut(id=c.id, name=c.name, product_count=c.product_count)
|
|
for c in qs
|
|
]
|
|
|
|
@router.get("/productos", response=list[ProductListOut])
|
|
def listar_productos(request, categoria_id: Optional[int] = None):
|
|
qs = Product.objects.select_related("category", "primary_image")
|
|
if categoria_id:
|
|
qs = qs.filter(category_id=categoria_id)
|
|
return [_product_to_list_out(p, request) for p in qs]
|
|
|
|
@router.get("/productos/{product_id}", response=ProductDetailOut)
|
|
def detalle_producto(request, product_id: int):
|
|
p = get_object_or_404(
|
|
Product.objects.select_related("category", "primary_image")
|
|
.prefetch_related("secondary_images"),
|
|
id=product_id,
|
|
)
|
|
return _product_to_detail_out(p, request)
|