Created
June 20, 2023 05:13
-
-
Save ItsCalebJones/209f99004f5f4bf62df66f2db15c4a8c to your computer and use it in GitHub Desktop.
Attempting to Implement PolymorphicSerializer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django_filters.rest_framework import DjangoFilterBackend | |
from drf_spectacular.utils import OpenApiParameter, extend_schema, extend_schema_view | |
from rest_framework.filters import OrderingFilter, SearchFilter | |
from api.endpoints.common.views import BaseModelViewSet | |
from api.models import Launch | |
from api.permission import HasGroupPermission | |
from ...common.prefetches import get_prefetched_launch_queryset | |
from ...launch.filters import LaunchFilterSet | |
from ...launch.serializers import LaunchDetailedSerializer, LaunchListSerializer, LaunchSerializerCommon | |
from .common import check_common_filters | |
from drf_spectacular.utils import PolymorphicProxySerializer | |
polymorphic_serializer = PolymorphicProxySerializer( | |
component_name="MetaLaunch", | |
serializers=[LaunchListSerializer, LaunchSerializerCommon], | |
resource_type_field_name="type", | |
) | |
poly_extend = extend_schema( | |
responses={ | |
200: polymorphic_serializer, | |
}, | |
parameters=[ | |
OpenApiParameter( | |
name="lsp__name", | |
type=str, | |
location=OpenApiParameter.QUERY, | |
), | |
OpenApiParameter( | |
name="lsp__id", | |
type=int, | |
location=OpenApiParameter.QUERY, | |
), | |
OpenApiParameter( | |
name="related", | |
type=bool, | |
location=OpenApiParameter.QUERY, | |
description="Include related agencies in the lsp__name and lsp__id filters.", | |
), | |
OpenApiParameter( | |
name="location__ids", | |
type=int, | |
many=True, | |
location=OpenApiParameter.QUERY, | |
), | |
OpenApiParameter( | |
name="lsp__ids", | |
type=int, | |
many=True, | |
location=OpenApiParameter.QUERY, | |
), | |
OpenApiParameter( | |
name="pad__ids", | |
type=int, | |
many=True, | |
location=OpenApiParameter.QUERY, | |
), | |
OpenApiParameter( | |
name="strict_filtering", | |
type=bool, | |
location=OpenApiParameter.QUERY, | |
description="Enforce strict filtering for lsp__ids, location__ids, and pad__ids. " | |
"False by default for backwards-compatibility.", | |
), | |
], | |
) | |
@extend_schema_view( | |
list=poly_extend, | |
retrieve=poly_extend, | |
) | |
class LaunchViewSet(BaseModelViewSet): | |
""" | |
AN API endpoint that returns all Launch objects or a single launch. | |
EXAMPLE - /launch/\<id\>/ or /launch/?mode=list&search=SpaceX | |
GET | |
Return a list of all Launch objects. | |
FILTERS | |
Fields - 'name', 'id(s)', 'lsp__id', 'lsp__name', 'serial_number', 'launcher_config__id', | |
'rocket__spacecraftflight__spacecraft__name', 'is_crewed', 'include_suborbital', 'spacecraft_config__ids', | |
'related', 'location__ids', 'lsp__ids', 'pad__ids', 'status__ids' | |
MODE | |
'normal', 'list', 'detailed' | |
EXAMPLE ?mode=list | |
SEARCH | |
Searches through the launch name, rocket name, launch agency, mission name & spacecraft name. | |
EXAMPLE - ?search=SpaceX | |
""" | |
def get_queryset(self): | |
lsp_name = self.request.query_params.get("lsp__name", None) | |
lsp_id = self.request.query_params.get("lsp__id", None) | |
location_filters = self.request.query_params.get("location__ids", None) | |
lsp_filters = self.request.query_params.get("lsp__ids", None) | |
related = self.request.query_params.get("related", None) | |
pad_filters = self.request.query_params.get("pad__ids", None) | |
strict = self.request.query_params.get("strict_filtering", None) | |
launches = Launch.objects.all() | |
launches = check_common_filters( | |
launches, | |
location_filters, | |
lsp_filters, | |
lsp_id, | |
lsp_name, | |
pad_filters, | |
related, | |
strict, | |
) | |
mode = self.request.query_params.get("mode", "normal") | |
return ( | |
get_prefetched_launch_queryset(launches, mode == "detailed") | |
.order_by("net", "net_precision", "name") | |
.distinct() | |
) | |
def get_serializer_class(self): | |
mode = self.request.query_params.get("mode", "normal") | |
if self.action == "retrieve" or mode == "detailed": | |
return LaunchDetailedSerializer | |
elif mode == "list": | |
return LaunchListSerializer | |
else: | |
return LaunchSerializerCommon | |
permission_classes = [HasGroupPermission] | |
permission_groups = {"retrieve": ["_Public"], "list": ["_Public"]} | |
filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter) | |
filter_class = LaunchFilterSet | |
search_fields = ( | |
"name", | |
"rocket__configuration__name", | |
"rocket__configuration__manufacturer__name", | |
"launch_service_provider__name", | |
"rocket__configuration__manufacturer__abbrev", | |
"mission__name", | |
"pad__location__name", | |
"pad__name", | |
"rocket__spacecraftflight__spacecraft__name", | |
) | |
ordering_fields = ( | |
"id", | |
"name", | |
"net", | |
"last_updated", | |
) | |
http_method_names = ["get"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class LaunchListSerializer(serializers.ModelSerializer): | |
pad = serializers.StringRelatedField(source="pad.name") | |
location = serializers.StringRelatedField(source="pad.location") | |
status = LaunchStatusSerializer(many=False, read_only=True) | |
net_precision = NetPrecisionSerializer(many=False, read_only=True) | |
landing = serializers.SerializerMethodField() | |
landing_success = serializers.SerializerMethodField() | |
launcher = serializers.SerializerMethodField() | |
orbit = serializers.SerializerMethodField() | |
mission = serializers.StringRelatedField() | |
image = serializers.SerializerMethodField() | |
infographic = serializers.SerializerMethodField() | |
mission_type = serializers.StringRelatedField(source="mission.mission_type.name") | |
slug = serializers.SlugField(source="get_absolute_url") | |
lsp_name = serializers.StringRelatedField(source="launch_service_provider.name") | |
type = serializers.SerializerMethodField() | |
class Meta: | |
model = Launch | |
fields = ( | |
"id", | |
"url", | |
"slug", | |
"name", | |
"status", | |
"last_updated", | |
"net", | |
"net_precision", | |
"window_end", | |
"window_start", | |
"lsp_name", | |
"mission", | |
"mission_type", | |
"pad", | |
"location", | |
"landing", | |
"landing_success", | |
"launcher", | |
"orbit", | |
"image", | |
"infographic", | |
"type" | |
) | |
def get_type(self, obj) -> str: | |
return 'list' | |
... | |
class LaunchSerializerCommon(serializers.HyperlinkedModelSerializer): | |
pad = PadSerializer(many=False, read_only=True) | |
rocket = RocketSerializerCommon(many=False, read_only=True) | |
mission = MissionSerializer(many=False, read_only=True) | |
status = LaunchStatusSerializer(many=False, read_only=True) | |
net_precision = NetPrecisionSerializer(many=False, read_only=True) | |
slug = serializers.SlugField(source="get_absolute_url") | |
launch_service_provider = AgencySerializerMini(read_only=True) | |
program = ProgramSerializer(many=True, read_only=True) | |
image = serializers.SerializerMethodField() | |
infographic = serializers.SerializerMethodField() | |
type = serializers.SerializerMethodField() | |
class Meta: | |
depth = 3 | |
model = Launch | |
fields = ( | |
"id", | |
"url", | |
"slug", | |
"name", | |
"status", | |
"last_updated", | |
"net", | |
"window_end", | |
"window_start", | |
"net_precision", | |
"probability", | |
"weather_concerns", | |
"holdreason", | |
"failreason", | |
"hashtag", | |
"launch_service_provider", | |
"rocket", | |
"mission", | |
"pad", | |
"webcast_live", | |
"image", | |
"infographic", | |
"program", | |
"orbital_launch_attempt_count", | |
"location_launch_attempt_count", | |
"pad_launch_attempt_count", | |
"agency_launch_attempt_count", | |
"orbital_launch_attempt_count_year", | |
"location_launch_attempt_count_year", | |
"pad_launch_attempt_count_year", | |
"agency_launch_attempt_count_year", | |
"type" | |
) | |
def get_type(self, obj) -> str: | |
return 'normal' | |
... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment