64 lines
1.9 KiB
Python
64 lines
1.9 KiB
Python
"""
|
|
Global search API routes.
|
|
"""
|
|
from typing import List
|
|
from ninja import Router, Schema
|
|
from django.db.models import Count, Q
|
|
from django.conf import settings
|
|
from django.views.decorators.cache import cache_page
|
|
|
|
from apps.products.models import Product, Website
|
|
from apps.products.schemas import ProductOut, WebsiteOut
|
|
from apps.bounties.models import Bounty
|
|
from apps.bounties.schemas import BountyWithDetailsOut
|
|
from apps.common.serializers import serialize_bounty
|
|
|
|
router = Router()
|
|
|
|
|
|
class SearchResultsOut(Schema):
|
|
products: List[ProductOut]
|
|
websites: List[WebsiteOut]
|
|
bounties: List[BountyWithDetailsOut]
|
|
|
|
|
|
def _serialize_bounty_with_counts(bounty):
|
|
return serialize_bounty(bounty, include_counts=True)
|
|
|
|
|
|
@router.get("/", response=SearchResultsOut)
|
|
@cache_page(settings.CACHE_TTL_SECONDS)
|
|
def global_search(request, q: str, limit: int = 10):
|
|
"""Search products, websites and bounties by keyword."""
|
|
keyword = (q or "").strip()
|
|
if not keyword:
|
|
return SearchResultsOut(products=[], websites=[], bounties=[])
|
|
|
|
products = list(
|
|
Product.objects.select_related("category").filter(
|
|
Q(name__icontains=keyword) | Q(description__icontains=keyword)
|
|
).order_by("-created_at")[:limit]
|
|
)
|
|
|
|
websites = list(
|
|
Website.objects.select_related("category").filter(
|
|
Q(name__icontains=keyword) | Q(description__icontains=keyword)
|
|
).order_by("-created_at")[:limit]
|
|
)
|
|
|
|
bounties = list(
|
|
Bounty.objects.select_related("publisher", "acceptor")
|
|
.annotate(
|
|
applications_count=Count("applications", distinct=True),
|
|
comments_count=Count("comments", distinct=True),
|
|
)
|
|
.filter(Q(title__icontains=keyword) | Q(description__icontains=keyword))
|
|
.order_by("-created_at")[:limit]
|
|
)
|
|
|
|
return SearchResultsOut(
|
|
products=products,
|
|
websites=websites,
|
|
bounties=[_serialize_bounty_with_counts(b) for b in bounties],
|
|
)
|