pokeapi/pokemon_v2/api.py
2023-11-08 10:44:55 +01:00

447 lines
14 KiB
Python

import re
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.views import APIView
from django.shortcuts import get_object_or_404
from django.http import Http404
from .models import *
from .serializers import *
# pylint: disable=no-member, attribute-defined-outside-init
###########################
# BEHAVIOR ABSTRACTIONS #
###########################
class ListOrDetailSerialRelation:
"""
Mixin to allow association with separate serializers
for list or detail view.
"""
list_serializer_class = None
def get_serializer_class(self):
if self.action == "list" and self.list_serializer_class is not None:
return self.list_serializer_class
return self.serializer_class
class NameOrIdRetrieval:
"""
Mixin to allow retrieval of resources by
pk (in this case ID) or by name
"""
idPattern = re.compile(r"^-?[0-9]+$")
namePattern = re.compile(r"^[0-9A-Za-z\-\+]+$")
def get_object(self):
queryset = self.get_queryset()
queryset = self.filter_queryset(queryset)
lookup = self.kwargs["pk"]
if self.idPattern.match(lookup):
lookup_id = int(lookup)
if abs(lookup_id) > 2147483647:
raise Http404
resp = get_object_or_404(queryset, pk=lookup)
elif self.namePattern.match(lookup):
resp = get_object_or_404(queryset, name=lookup)
else:
raise Http404
return resp
class PokeapiCommonViewset(
ListOrDetailSerialRelation, NameOrIdRetrieval, viewsets.ReadOnlyModelViewSet
):
pass
##########
# APIS #
##########
class AbilityResource(PokeapiCommonViewset):
queryset = Ability.objects.all()
serializer_class = AbilityDetailSerializer
list_serializer_class = AbilitySummarySerializer
class BerryResource(PokeapiCommonViewset):
queryset = Berry.objects.all()
serializer_class = BerryDetailSerializer
list_serializer_class = BerrySummarySerializer
class BerryFirmnessResource(PokeapiCommonViewset):
queryset = BerryFirmness.objects.all()
serializer_class = BerryFirmnessDetailSerializer
list_serializer_class = BerryFirmnessSummarySerializer
class BerryFlavorResource(PokeapiCommonViewset):
queryset = BerryFlavor.objects.all()
serializer_class = BerryFlavorDetailSerializer
list_serializer_class = BerryFlavorSummarySerializer
class CharacteristicResource(PokeapiCommonViewset):
queryset = Characteristic.objects.all()
serializer_class = CharacteristicDetailSerializer
list_serializer_class = CharacteristicSummarySerializer
class ContestEffectResource(PokeapiCommonViewset):
queryset = ContestEffect.objects.all()
serializer_class = ContestEffectDetailSerializer
list_serializer_class = ContestEffectSummarySerializer
class ContestTypeResource(PokeapiCommonViewset):
queryset = ContestType.objects.all()
serializer_class = ContestTypeDetailSerializer
list_serializer_class = ContestTypeSummarySerializer
class EggGroupResource(PokeapiCommonViewset):
queryset = EggGroup.objects.all()
serializer_class = EggGroupDetailSerializer
list_serializer_class = EggGroupSummarySerializer
class EncounterConditionResource(PokeapiCommonViewset):
queryset = EncounterCondition.objects.all()
serializer_class = EncounterConditionDetailSerializer
list_serializer_class = EncounterConditionSummarySerializer
class EncounterConditionValueResource(PokeapiCommonViewset):
queryset = EncounterConditionValue.objects.all()
serializer_class = EncounterConditionValueDetailSerializer
list_serializer_class = EncounterConditionValueSummarySerializer
class EncounterMethodResource(PokeapiCommonViewset):
queryset = EncounterMethod.objects.all()
serializer_class = EncounterMethodDetailSerializer
list_serializer_class = EncounterMethodSummarySerializer
class EvolutionChainResource(PokeapiCommonViewset):
queryset = EvolutionChain.objects.all()
serializer_class = EvolutionChainDetailSerializer
list_serializer_class = EvolutionChainSummarySerializer
class EvolutionTriggerResource(PokeapiCommonViewset):
queryset = EvolutionTrigger.objects.all()
serializer_class = EvolutionTriggerDetailSerializer
list_serializer_class = EvolutionTriggerSummarySerializer
class GenerationResource(PokeapiCommonViewset):
queryset = Generation.objects.all()
serializer_class = GenerationDetailSerializer
list_serializer_class = GenerationSummarySerializer
class GenderResource(PokeapiCommonViewset):
queryset = Gender.objects.all()
serializer_class = GenderDetailSerializer
list_serializer_class = GenderSummarySerializer
class GrowthRateResource(PokeapiCommonViewset):
queryset = GrowthRate.objects.all()
serializer_class = GrowthRateDetailSerializer
list_serializer_class = GrowthRateSummarySerializer
class ItemResource(PokeapiCommonViewset):
queryset = Item.objects.all()
serializer_class = ItemDetailSerializer
list_serializer_class = ItemSummarySerializer
class ItemCategoryResource(PokeapiCommonViewset):
queryset = ItemCategory.objects.all()
serializer_class = ItemCategoryDetailSerializer
list_serializer_class = ItemCategorySummarySerializer
class ItemAttributeResource(PokeapiCommonViewset):
queryset = ItemAttribute.objects.all()
serializer_class = ItemAttributeDetailSerializer
list_serializer_class = ItemAttributeSummarySerializer
class ItemFlingEffectResource(PokeapiCommonViewset):
queryset = ItemFlingEffect.objects.all()
serializer_class = ItemFlingEffectDetailSerializer
list_serializer_class = ItemFlingEffectSummarySerializer
class ItemPocketResource(PokeapiCommonViewset):
queryset = ItemPocket.objects.all()
serializer_class = ItemPocketDetailSerializer
list_serializer_class = ItemPocketSummarySerializer
class LanguageResource(PokeapiCommonViewset):
queryset = Language.objects.all()
serializer_class = LanguageDetailSerializer
list_serializer_class = LanguageSummarySerializer
class LocationResource(PokeapiCommonViewset):
queryset = Location.objects.all()
serializer_class = LocationDetailSerializer
list_serializer_class = LocationSummarySerializer
class LocationAreaResource(ListOrDetailSerialRelation, viewsets.ReadOnlyModelViewSet):
queryset = LocationArea.objects.all()
serializer_class = LocationAreaDetailSerializer
list_serializer_class = LocationAreaSummarySerializer
class MachineResource(PokeapiCommonViewset):
queryset = Machine.objects.all()
serializer_class = MachineDetailSerializer
list_serializer_class = MachineSummarySerializer
class MoveResource(PokeapiCommonViewset):
queryset = Move.objects.all()
serializer_class = MoveDetailSerializer
list_serializer_class = MoveSummarySerializer
class MoveDamageClassResource(PokeapiCommonViewset):
queryset = MoveDamageClass.objects.all()
serializer_class = MoveDamageClassDetailSerializer
list_serializer_class = MoveDamageClassSummarySerializer
class MoveMetaAilmentResource(PokeapiCommonViewset):
queryset = MoveMetaAilment.objects.all()
serializer_class = MoveMetaAilmentDetailSerializer
list_serializer_class = MoveMetaAilmentSummarySerializer
class MoveBattleStyleResource(PokeapiCommonViewset):
queryset = MoveBattleStyle.objects.all()
serializer_class = MoveBattleStyleDetailSerializer
list_serializer_class = MoveBattleStyleSummarySerializer
class MoveMetaCategoryResource(PokeapiCommonViewset):
queryset = MoveMetaCategory.objects.all()
serializer_class = MoveMetaCategoryDetailSerializer
list_serializer_class = MoveMetaCategorySummarySerializer
class MoveLearnMethodResource(PokeapiCommonViewset):
queryset = MoveLearnMethod.objects.all()
serializer_class = MoveLearnMethodDetailSerializer
list_serializer_class = MoveLearnMethodSummarySerializer
class MoveTargetResource(PokeapiCommonViewset):
queryset = MoveTarget.objects.all()
serializer_class = MoveTargetDetailSerializer
list_serializer_class = MoveTargetSummarySerializer
class NatureResource(PokeapiCommonViewset):
queryset = Nature.objects.all()
serializer_class = NatureDetailSerializer
list_serializer_class = NatureSummarySerializer
class PalParkAreaResource(PokeapiCommonViewset):
queryset = PalParkArea.objects.all()
serializer_class = PalParkAreaDetailSerializer
list_serializer_class = PalParkAreaSummarySerializer
class PokeathlonStatResource(PokeapiCommonViewset):
queryset = PokeathlonStat.objects.all()
serializer_class = PokeathlonStatDetailSerializer
list_serializer_class = PokeathlonStatSummarySerializer
class PokedexResource(PokeapiCommonViewset):
queryset = Pokedex.objects.all()
serializer_class = PokedexDetailSerializer
list_serializer_class = PokedexSummarySerializer
class PokemonColorResource(PokeapiCommonViewset):
queryset = PokemonColor.objects.all()
serializer_class = PokemonColorDetailSerializer
list_serializer_class = PokemonColorSummarySerializer
class PokemonFormResource(PokeapiCommonViewset):
queryset = PokemonForm.objects.all()
serializer_class = PokemonFormDetailSerializer
list_serializer_class = PokemonFormSummarySerializer
class PokemonHabitatResource(PokeapiCommonViewset):
queryset = PokemonHabitat.objects.all()
serializer_class = PokemonHabitatDetailSerializer
list_serializer_class = PokemonHabitatSummarySerializer
class PokemonShapeResource(PokeapiCommonViewset):
queryset = PokemonShape.objects.all()
serializer_class = PokemonShapeDetailSerializer
list_serializer_class = PokemonShapeSummarySerializer
class PokemonResource(PokeapiCommonViewset):
queryset = Pokemon.objects.all()
serializer_class = PokemonDetailSerializer
list_serializer_class = PokemonSummarySerializer
class PokemonSpeciesResource(PokeapiCommonViewset):
queryset = PokemonSpecies.objects.all().order_by("id")
serializer_class = PokemonSpeciesDetailSerializer
list_serializer_class = PokemonSpeciesSummarySerializer
class RegionResource(PokeapiCommonViewset):
queryset = Region.objects.all()
serializer_class = RegionDetailSerializer
list_serializer_class = RegionSummarySerializer
class StatResource(PokeapiCommonViewset):
queryset = Stat.objects.all()
serializer_class = StatDetailSerializer
list_serializer_class = StatSummarySerializer
class SuperContestEffectResource(PokeapiCommonViewset):
queryset = SuperContestEffect.objects.all()
serializer_class = SuperContestEffectDetailSerializer
list_serializer_class = SuperContestEffectSummarySerializer
class TypeResource(PokeapiCommonViewset):
queryset = Type.objects.all()
serializer_class = TypeDetailSerializer
list_serializer_class = TypeSummarySerializer
class VersionResource(PokeapiCommonViewset):
queryset = Version.objects.all()
serializer_class = VersionDetailSerializer
list_serializer_class = VersionSummarySerializer
class VersionGroupResource(PokeapiCommonViewset):
queryset = VersionGroup.objects.all()
serializer_class = VersionGroupDetailSerializer
list_serializer_class = VersionGroupSummarySerializer
class PokemonEncounterView(APIView):
"""
Handles Pokemon Encounters as a sub-resource.
"""
def get(self, request, pokemon_id):
self.context = dict(request=request)
try:
pokemon = Pokemon.objects.get(pk=pokemon_id)
except Pokemon.DoesNotExist:
raise Http404
encounter_objects = Encounter.objects.filter(pokemon=pokemon)
area_ids = (
encounter_objects.order_by("location_area")
.distinct("location_area")
.values_list("location_area", flat=True)
)
location_area_objects = LocationArea.objects.filter(pk__in=area_ids)
version_objects = Version.objects
encounters_list = []
for area_id in area_ids:
location_area = location_area_objects.get(pk=area_id)
area_encounters = encounter_objects.filter(location_area_id=area_id)
version_ids = (
area_encounters.order_by("version_id")
.distinct("version_id")
.values_list("version_id", flat=True)
)
version_details_list = []
for version_id in version_ids:
version = version_objects.get(pk=version_id)
version_encounters = area_encounters.filter(
version_id=version_id
).order_by("encounter_slot_id")
encounters_data = EncounterDetailSerializer(
version_encounters, many=True, context=self.context
).data
max_chance = 0
encounter_details_list = []
for encounter in encounters_data:
slot = EncounterSlot.objects.get(pk=encounter["encounter_slot"])
slot_data = EncounterSlotSerializer(slot, context=self.context).data
del encounter["pokemon"]
del encounter["encounter_slot"]
del encounter["location_area"]
del encounter["version"]
encounter["chance"] = slot_data["chance"]
max_chance += slot_data["chance"]
encounter["method"] = slot_data["encounter_method"]
encounter_details_list.append(encounter)
version_details_list.append(
{
"version": VersionSummarySerializer(
version, context=self.context
).data,
"max_chance": max_chance,
"encounter_details": encounter_details_list,
}
)
encounters_list.append(
{
"location_area": LocationAreaSummarySerializer(
location_area, context=self.context
).data,
"version_details": version_details_list,
}
)
return Response(encounters_list)