feat: Add public event listing REST API endpoint#2773
feat: Add public event listing REST API endpoint#2773OsauravO wants to merge 2 commits intofossasia:devfrom
Conversation
Reviewer's GuideAdds a new unauthenticated, read-only REST endpoint Sequence diagram for public events listing API requestsequenceDiagram
actor Client
participant Router
participant PublicEventViewSet
participant PublicEventFilter
participant EventModel
participant PublicEventSerializer
Client->>Router: GET /api/v1/events/?q=conf&organizer=testorg&is_future=true
Router->>PublicEventViewSet: dispatch list
activate PublicEventViewSet
PublicEventViewSet->>PublicEventViewSet: get_queryset()
PublicEventViewSet->>EventModel: filter(live=True, is_public=True)
EventModel-->>PublicEventViewSet: base_queryset
PublicEventViewSet->>EventModel: exclude(testmode=True)
EventModel-->>PublicEventViewSet: filtered_queryset
PublicEventViewSet->>PublicEventFilter: apply filters(q, organizer, is_future, is_past, has_subevents)
activate PublicEventFilter
PublicEventFilter->>EventModel: search_qs(name__icontains=q)
EventModel-->>PublicEventFilter: queryset
PublicEventFilter->>EventModel: is_future_qs(now_based_expression)
EventModel-->>PublicEventFilter: queryset
PublicEventFilter-->>PublicEventViewSet: filtered_queryset
deactivate PublicEventFilter
PublicEventViewSet->>PublicEventSerializer: serialize(paginated_queryset, many=True)
PublicEventSerializer-->>PublicEventViewSet: response_data
deactivate PublicEventViewSet
PublicEventViewSet-->>Client: 200 OK (paginated public event list)
Class diagram for public events API componentsclassDiagram
class Event {
+UUID id
+string slug
+string name
+bool live
+bool is_public
+bool testmode
+bool has_subevents
+datetime date_from
+datetime date_to
+string location
+string currency
+float geo_lat
+float geo_lon
}
class I18nAwareModelSerializer {
}
class PublicEventSerializer {
+organizer SlugRelatedField
+Meta meta
}
class PublicEventSerializer_Meta {
+model Event
+fields name, slug, organizer, date_from, date_to,
+fields location, currency, has_subevents, geo_lat, geo_lon
+read_only_fields fields
}
class FilterSet {
}
class PublicEventFilter {
+BooleanFilter is_past
+BooleanFilter is_future
+CharFilter organizer
+CharFilter q
+Meta meta
+is_past_qs(queryset, name, value) QuerySet
+is_future_qs(queryset, name, value) QuerySet
+search_qs(queryset, name, value) QuerySet
}
class PublicEventFilter_Meta {
+model Event
+fields has_subevents
}
class GenericViewSet {
}
class ListModelMixin {
}
class RetrieveModelMixin {
}
class PublicEventViewSet {
+serializer_class PublicEventSerializer
+queryset QuerySet
+permission_classes AllowAny
+authentication_classes empty_tuple
+lookup_field slug
+filter_backends DjangoFilterBackend, OrderingFilter
+ordering date_from
+ordering_fields date_from, name, slug
+filterset_class PublicEventFilter
+get_queryset() QuerySet
}
class AllowAny {
}
class DjangoFilterBackend {
}
class OrderingFilter {
}
PublicEventSerializer --|> I18nAwareModelSerializer
PublicEventSerializer_Meta --|> PublicEventSerializer
PublicEventFilter --|> FilterSet
PublicEventFilter_Meta --|> PublicEventFilter
PublicEventViewSet --|> GenericViewSet
PublicEventViewSet --|> ListModelMixin
PublicEventViewSet --|> RetrieveModelMixin
PublicEventViewSet --> PublicEventSerializer : uses
PublicEventViewSet --> PublicEventFilter : uses
PublicEventViewSet --> AllowAny : permission_classes
PublicEventViewSet --> DjangoFilterBackend : filter_backends
PublicEventViewSet --> OrderingFilter : filter_backends
PublicEventFilter --> Event : filters
PublicEventSerializer --> Event : model
EventModel <|-- Event
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The
PublicEventFilterduplicatesis_past_qs/is_future_qslogic already present inEventFilter; consider extracting the shared date-range predicates into a reusable helper or base class to keep this logic consistent and easier to maintain. - In
PublicEventViewSet, you might want to reuse any existing search behavior (e.g., i18n-aware name search or slug search) instead ofname__icontainsonly, so that the public listing behaves consistently with other event search endpoints.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `PublicEventFilter` duplicates `is_past_qs`/`is_future_qs` logic already present in `EventFilter`; consider extracting the shared date-range predicates into a reusable helper or base class to keep this logic consistent and easier to maintain.
- In `PublicEventViewSet`, you might want to reuse any existing search behavior (e.g., i18n-aware name search or slug search) instead of `name__icontains` only, so that the public listing behaves consistently with other event search endpoints.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Pull request overview
Adds a new public, unauthenticated REST API surface for browsing public, live events, complementing the existing organizer-scoped (authenticated) events API.
Changes:
- Introduces
PublicEventSerializerto expose a restricted, public-safe subset ofEventfields. - Adds
PublicEventViewSet+PublicEventFilterto provide read-only list/retrieve with filtering/ordering for public events. - Registers the new viewset under
/api/v1/events/.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| app/eventyay/api/views/event.py | Adds the new public viewset + filter and public-event queryset selection. |
| app/eventyay/api/serializers/event.py | Adds a restricted serializer for public event exposure. |
| app/eventyay/api/urls.py | Registers /api/v1/events/ route via the DRF router. |
| return queryset.filter(name__icontains=value) | ||
|
|
||
|
|
||
| class PublicEventViewSet(viewsets.GenericViewSet, viewsets.mixins.ListModelMixin, viewsets.mixins.RetrieveModelMixin): |
| lookup_field = 'slug' | ||
| filter_backends = (DjangoFilterBackend, filters.OrderingFilter) | ||
| ordering = ('date_from',) | ||
| ordering_fields = ('date_from', 'name', 'slug') | ||
| filterset_class = PublicEventFilter |
|
|
||
| router = routers.DefaultRouter() | ||
| router.register(r'organizers', organizer.OrganizerViewSet) | ||
| router.register(r'events', event.PublicEventViewSet, basename='public-events') |
|
Thanks for the effort. Closing this PR because we do not want to introduce unauthenticated REST endpoints for event data. It is preferred to keep API access under a consistent authenticated model instead of exposing a parallel public API, even for fields that are already visible in the frontend. Public page visibility and public API access are not the same product decision, and the latter carries a larger longterm maintenance and compatibility burden. |
|
Thanks for review, understood, that makes sense. I will keep this in mind for future contributions. |
Summary
Fixes #2772
Adds a new read-only REST API endpoint at
GET /api/v1/events/that allowsunauthenticated users to browse public, live events. Previously, theEventViewSetat/api/v1/organizers/{organizer}/events/returned 403 forunauthenticated requests, even though the same event data was publicly visibleon the HTML start page.
Changes
app/eventyay/api/serializers/event.py— AddedPublicEventSerializerwith a limited set of public-safe fields (name, slug, organizer, dates,location, currency, geo coordinates, has_subevents). Sensitive fields like plugins, sales_channels, meta_data, seating_plan, and valid_keys are excluded.app/eventyay/api/views/event.py— AddedPublicEventFilter(search by name, filter by organizer/past/future) andPublicEventViewSet(read-only, no authentication required). The queryset filters forlive=True,is_public=True, and excludes test-mode events.app/eventyay/api/urls.py— Registered the new viewset at/api/v1/events/.API
/api/v1/events//api/v1/events/{slug}/Query parameters:
?q=(name search),?organizer=(filter by slug),?is_future=true/false,?is_past=true/false,?has_subevents=true/false,?ordering=date_from/-date_from/name/slugExample response:
Summary by Sourcery
Add a public, read-only REST endpoint to list and retrieve live public events by slug.
New Features:
/api/v1/events/endpoint that lets unauthenticated users list and view public, live events by slug using a restricted public serializer.Enhancements:
PublicEventSerializerand filter set to expose only non-sensitive event fields with basic search, filtering, and ordering options via the new endpoint.