Add GET /api/club/{club_id} to fetch details about a club

This commit is contained in:
imperosol 2025-05-20 18:17:48 +02:00
parent f72a93a673
commit 2223086bb6
6 changed files with 55 additions and 11 deletions

View File

@ -1,13 +1,15 @@
from typing import Annotated
from annotated_types import MinLen
from ninja.security import SessionAuth
from ninja_extra import ControllerBase, api_controller, paginate, route
from ninja_extra.pagination import PageNumberPaginationExtra
from ninja_extra.schemas import PaginatedResponseSchema
from apikey.auth import ApiKeyAuth
from club.models import Club
from club.schemas import ClubSchema
from core.auth.api_permissions import CanAccessLookup
from core.auth.api_permissions import CanAccessLookup, HasPerm
@api_controller("/club")
@ -20,3 +22,14 @@ class ClubController(ControllerBase):
@paginate(PageNumberPaginationExtra, page_size=50)
def search_club(self, search: Annotated[str, MinLen(1)]):
return Club.objects.filter(name__icontains=search).values()
@route.get(
"/{int:club_id}",
response=ClubSchema,
auth=[SessionAuth(), ApiKeyAuth()],
permissions=[HasPerm("club.view_club")],
)
def fetch_club(self, club_id: int):
return self.get_object_or_exception(
Club.objects.prefetch_related("members", "members__user"), id=club_id
)

View File

@ -1,9 +1,10 @@
from ninja import ModelSchema
from club.models import Club
from club.models import Club, Membership
from core.schemas import SimpleUserSchema
class ClubSchema(ModelSchema):
class SimpleClubSchema(ModelSchema):
class Meta:
model = Club
fields = ["id", "name"]
@ -21,3 +22,19 @@ class ClubProfileSchema(ModelSchema):
@staticmethod
def resolve_url(obj: Club) -> str:
return obj.get_absolute_url()
class ClubMemberSchema(ModelSchema):
class Meta:
model = Membership
fields = ["start_date", "end_date", "role", "description"]
user: SimpleUserSchema
class ClubSchema(ModelSchema):
class Meta:
model = Club
fields = ["id", "name", "logo", "is_active", "short_description", "address"]
members: list[ClubMemberSchema]

View File

@ -0,0 +1,16 @@
import pytest
from model_bakery import baker
from ninja_extra.testing import TestClient
from pytest_django.asserts import assertNumQueries
from club.api import ClubController
from club.models import Club, Membership
@pytest.mark.django_db
def test_fetch_club():
club = baker.make(Club)
baker.make(Membership, club=club, _quantity=10, _bulk_create=True)
with assertNumQueries(3):
res = TestClient(ClubController).get(f"/{club.id}")
assert res.status_code == 200

View File

@ -1,7 +1,7 @@
from pydantic import TypeAdapter
from club.models import Club
from club.schemas import ClubSchema
from club.schemas import SimpleClubSchema
from core.views.widgets.ajax_select import (
AutoCompleteSelect,
AutoCompleteSelectMultiple,
@ -13,7 +13,7 @@ _js = ["bundled/club/components/ajax-select-index.ts"]
class AutoCompleteSelectClub(AutoCompleteSelect):
component_name = "club-ajax-select"
model = Club
adapter = TypeAdapter(list[ClubSchema])
adapter = TypeAdapter(list[SimpleClubSchema])
js = _js
@ -21,6 +21,6 @@ class AutoCompleteSelectClub(AutoCompleteSelect):
class AutoCompleteSelectMultipleClub(AutoCompleteSelectMultiple):
component_name = "club-ajax-select"
model = Club
adapter = TypeAdapter(list[ClubSchema])
adapter = TypeAdapter(list[SimpleClubSchema])
js = _js

View File

@ -5,7 +5,7 @@ from django.urls import reverse
from ninja import Field, FilterSchema, ModelSchema, Schema
from pydantic import model_validator
from club.schemas import ClubSchema
from club.schemas import SimpleClubSchema
from core.schemas import GroupSchema, SimpleUserSchema
from counter.models import Counter, Product, ProductType
@ -82,7 +82,7 @@ class ProductSchema(ModelSchema):
]
buying_groups: list[GroupSchema]
club: ClubSchema
club: SimpleClubSchema
product_type: SimpleProductTypeSchema | None
url: str

View File

@ -12,7 +12,6 @@
# OR WITHIN THE LOCAL FILE "LICENSE"
#
#
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
@ -26,8 +25,7 @@ js_info_dict = {"packages": ("sith",)}
handler403 = "core.views.forbidden"
handler404 = "core.views.not_found"
handler500 = "core.views.internal_servor_error"
api = NinjaExtraAPI(version="0.2.0", urls_namespace="api", csrf=True)
api = NinjaExtraAPI(title="Sith API", version="0.2.0", urls_namespace="api", csrf=True)
api.auto_discover_controllers()
urlpatterns = [