Skip to content

Instantly share code, notes, and snippets.

@ItsCalebJones
Created June 20, 2023 05:13
Show Gist options
  • Save ItsCalebJones/209f99004f5f4bf62df66f2db15c4a8c to your computer and use it in GitHub Desktop.
Save ItsCalebJones/209f99004f5f4bf62df66f2db15c4a8c to your computer and use it in GitHub Desktop.
Attempting to Implement PolymorphicSerializer
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"]
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