mirror of
https://github.com/ae-utbm/sith.git
synced 2025-06-08 12:15:18 +00:00
Add GET /api/club/{club_id}
to fetch details about a club
This commit is contained in:
parent
b2c6b4f747
commit
6f550c605c
15
club/api.py
15
club/api.py
@ -1,13 +1,15 @@
|
|||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
||||||
from annotated_types import MinLen
|
from annotated_types import MinLen
|
||||||
|
from ninja.security import SessionAuth
|
||||||
from ninja_extra import ControllerBase, api_controller, paginate, route
|
from ninja_extra import ControllerBase, api_controller, paginate, route
|
||||||
from ninja_extra.pagination import PageNumberPaginationExtra
|
from ninja_extra.pagination import PageNumberPaginationExtra
|
||||||
from ninja_extra.schemas import PaginatedResponseSchema
|
from ninja_extra.schemas import PaginatedResponseSchema
|
||||||
|
|
||||||
|
from apikey.auth import ApiKeyAuth
|
||||||
from club.models import Club
|
from club.models import Club
|
||||||
from club.schemas import ClubSchema
|
from club.schemas import ClubSchema
|
||||||
from core.auth.api_permissions import CanAccessLookup
|
from core.auth.api_permissions import CanAccessLookup, HasPerm
|
||||||
|
|
||||||
|
|
||||||
@api_controller("/club")
|
@api_controller("/club")
|
||||||
@ -20,3 +22,14 @@ class ClubController(ControllerBase):
|
|||||||
@paginate(PageNumberPaginationExtra, page_size=50)
|
@paginate(PageNumberPaginationExtra, page_size=50)
|
||||||
def search_club(self, search: Annotated[str, MinLen(1)]):
|
def search_club(self, search: Annotated[str, MinLen(1)]):
|
||||||
return Club.objects.filter(name__icontains=search).values()
|
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
|
||||||
|
)
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
from ninja import ModelSchema
|
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:
|
class Meta:
|
||||||
model = Club
|
model = Club
|
||||||
fields = ["id", "name"]
|
fields = ["id", "name"]
|
||||||
@ -21,3 +22,19 @@ class ClubProfileSchema(ModelSchema):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def resolve_url(obj: Club) -> str:
|
def resolve_url(obj: Club) -> str:
|
||||||
return obj.get_absolute_url()
|
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]
|
||||||
|
16
club/tests/test_club_controller.py
Normal file
16
club/tests/test_club_controller.py
Normal 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
|
@ -1,7 +1,7 @@
|
|||||||
from pydantic import TypeAdapter
|
from pydantic import TypeAdapter
|
||||||
|
|
||||||
from club.models import Club
|
from club.models import Club
|
||||||
from club.schemas import ClubSchema
|
from club.schemas import SimpleClubSchema
|
||||||
from core.views.widgets.ajax_select import (
|
from core.views.widgets.ajax_select import (
|
||||||
AutoCompleteSelect,
|
AutoCompleteSelect,
|
||||||
AutoCompleteSelectMultiple,
|
AutoCompleteSelectMultiple,
|
||||||
@ -13,7 +13,7 @@ _js = ["bundled/club/components/ajax-select-index.ts"]
|
|||||||
class AutoCompleteSelectClub(AutoCompleteSelect):
|
class AutoCompleteSelectClub(AutoCompleteSelect):
|
||||||
component_name = "club-ajax-select"
|
component_name = "club-ajax-select"
|
||||||
model = Club
|
model = Club
|
||||||
adapter = TypeAdapter(list[ClubSchema])
|
adapter = TypeAdapter(list[SimpleClubSchema])
|
||||||
|
|
||||||
js = _js
|
js = _js
|
||||||
|
|
||||||
@ -21,6 +21,6 @@ class AutoCompleteSelectClub(AutoCompleteSelect):
|
|||||||
class AutoCompleteSelectMultipleClub(AutoCompleteSelectMultiple):
|
class AutoCompleteSelectMultipleClub(AutoCompleteSelectMultiple):
|
||||||
component_name = "club-ajax-select"
|
component_name = "club-ajax-select"
|
||||||
model = Club
|
model = Club
|
||||||
adapter = TypeAdapter(list[ClubSchema])
|
adapter = TypeAdapter(list[SimpleClubSchema])
|
||||||
|
|
||||||
js = _js
|
js = _js
|
||||||
|
@ -5,7 +5,7 @@ from django.urls import reverse
|
|||||||
from ninja import Field, FilterSchema, ModelSchema, Schema
|
from ninja import Field, FilterSchema, ModelSchema, Schema
|
||||||
from pydantic import model_validator
|
from pydantic import model_validator
|
||||||
|
|
||||||
from club.schemas import ClubSchema
|
from club.schemas import SimpleClubSchema
|
||||||
from core.schemas import GroupSchema, SimpleUserSchema
|
from core.schemas import GroupSchema, SimpleUserSchema
|
||||||
from counter.models import Counter, Product, ProductType
|
from counter.models import Counter, Product, ProductType
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ class ProductSchema(ModelSchema):
|
|||||||
]
|
]
|
||||||
|
|
||||||
buying_groups: list[GroupSchema]
|
buying_groups: list[GroupSchema]
|
||||||
club: ClubSchema
|
club: SimpleClubSchema
|
||||||
product_type: SimpleProductTypeSchema | None
|
product_type: SimpleProductTypeSchema | None
|
||||||
url: str
|
url: str
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
# OR WITHIN THE LOCAL FILE "LICENSE"
|
# OR WITHIN THE LOCAL FILE "LICENSE"
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
@ -26,8 +25,7 @@ js_info_dict = {"packages": ("sith",)}
|
|||||||
handler403 = "core.views.forbidden"
|
handler403 = "core.views.forbidden"
|
||||||
handler404 = "core.views.not_found"
|
handler404 = "core.views.not_found"
|
||||||
handler500 = "core.views.internal_servor_error"
|
handler500 = "core.views.internal_servor_error"
|
||||||
|
api = NinjaExtraAPI(title="Sith API", version="0.2.0", urls_namespace="api", csrf=True)
|
||||||
api = NinjaExtraAPI(version="0.2.0", urls_namespace="api", csrf=True)
|
|
||||||
api.auto_discover_controllers()
|
api.auto_discover_controllers()
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user