Skip to content

Commit 9ed8e12

Browse files
committed
Add filtering and upcoming events
1 parent ba28462 commit 9ed8e12

File tree

3 files changed

+61
-7
lines changed

3 files changed

+61
-7
lines changed

backend/apps/api/rest/v0/chapter.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
from typing import Literal
66

77
from django.http import HttpRequest
8-
from ninja import Field, FilterSchema, Path, Query, Schema
8+
from ninja import Field, Path, Query, Schema
99
from ninja.decorators import decorate_view
1010
from ninja.pagination import RouterPaginated
1111
from ninja.responses import Response
1212

1313
from apps.api.decorators.cache import cache_response
14+
from apps.api.rest.v0.common import LocationFilter
1415
from apps.owasp.models.chapter import Chapter as ChapterModel
1516

1617
router = RouterPaginated(tags=["Chapters"])
@@ -23,6 +24,8 @@ class ChapterBase(Schema):
2324
key: str
2425
name: str
2526
updated_at: datetime
27+
longitude: float | None = None
28+
latitude: float | None = None
2629

2730
@staticmethod
2831
def resolve_key(obj):
@@ -49,7 +52,7 @@ class ChapterError(Schema):
4952
message: str
5053

5154

52-
class ChapterFilter(FilterSchema):
55+
class ChapterFilter(LocationFilter):
5356
"""Filter for Chapter."""
5457

5558
country: str | None = Field(None, description="Country of the chapter")
@@ -66,7 +69,17 @@ class ChapterFilter(FilterSchema):
6669
def list_chapters(
6770
request: HttpRequest,
6871
filters: ChapterFilter = Query(...),
69-
ordering: Literal["created_at", "-created_at", "updated_at", "-updated_at"] | None = Query(
72+
ordering: Literal[
73+
"created_at",
74+
"-created_at",
75+
"updated_at",
76+
"-updated_at",
77+
"longitude",
78+
"-longitude",
79+
"latitude",
80+
"-latitude",
81+
]
82+
| None = Query(
7083
None,
7184
description="Ordering field",
7285
),

backend/apps/api/rest/v0/common.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""Common schemas and filters for the API."""
2+
3+
from ninja import Field, FilterSchema
4+
5+
6+
class LocationFilter(FilterSchema):
7+
"""Filter for Location."""
8+
9+
longitude_gte: float | None = Field(
10+
None, description="Longitude greater than or equal to", q="longitude__gte"
11+
)
12+
longitude_lte: float | None = Field(
13+
None, description="Longitude less than or equal to", q="longitude__lte"
14+
)
15+
latitude_gte: float | None = Field(
16+
None, description="Latitude greater than or equal to", q="latitude__gte"
17+
)
18+
latitude_lte: float | None = Field(
19+
None, description="Latitude less than or equal to", q="latitude__lte"
20+
)

backend/apps/api/rest/v0/event.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from ninja.responses import Response
1212

1313
from apps.api.decorators.cache import cache_response
14+
from apps.api.rest.v0.common import LocationFilter
1415
from apps.owasp.models.event import Event as EventModel
1516

1617
router = RouterPaginated(tags=["Events"])
@@ -24,6 +25,8 @@ class EventBase(Schema):
2425
name: str
2526
start_date: datetime
2627
url: str | None = None
28+
longitude: float | None = None
29+
latitude: float | None = None
2730

2831

2932
class Event(EventBase):
@@ -34,8 +37,6 @@ class EventDetail(EventBase):
3437
"""Detail schema for Event (used in single item endpoints)."""
3538

3639
description: str | None = None
37-
longitude: float
38-
latitude: float
3940

4041

4142
class EventError(Schema):
@@ -54,13 +55,33 @@ class EventError(Schema):
5455
@decorate_view(cache_response())
5556
def list_events(
5657
request: HttpRequest,
57-
ordering: Literal["start_date", "-start_date", "end_date", "-end_date"] | None = Query(
58+
filters: LocationFilter = Query(...),
59+
ordering: Literal[
60+
"start_date", "-start_date", "end_date", "-end_date", "longitude", "-longitude"
61+
]
62+
| None = Query(
5863
None,
5964
description="Ordering field",
6065
),
6166
) -> list[Event]:
6267
"""Get all events."""
63-
return EventModel.objects.order_by(ordering or "-start_date", "-end_date")
68+
return filters.filter(EventModel.objects.order_by(ordering or "-start_date", "-end_date"))
69+
70+
71+
@router.get(
72+
"/upcoming",
73+
description="Retrieve a paginated list of upcoming OWASP events.",
74+
operation_id="list_upcoming_events",
75+
summary="List upcoming events",
76+
response=list[Event],
77+
)
78+
@decorate_view(cache_response())
79+
def list_upcoming_events(
80+
request: HttpRequest,
81+
filters: LocationFilter = Query(...),
82+
) -> list[Event]:
83+
"""Get upcoming events."""
84+
return filters.filter(EventModel.upcoming_events())
6485

6586

6687
@router.get(

0 commit comments

Comments
 (0)