feat: Add API methods for Animals, Images, Species andRescue orgs
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
moanos [he/him] 2024-11-24 22:29:19 +01:00
parent f6240a7189
commit c1332ee1f0
3 changed files with 169 additions and 12 deletions

View File

@ -1,10 +1,48 @@
from ..models import AdoptionNotice from ..models import Animal, RescueOrganization, AdoptionNotice, Species, Image
from rest_framework import serializers from rest_framework import serializers
class AdoptionNoticeSerializer(serializers.HyperlinkedModelSerializer): class AdoptionNoticeSerializer(serializers.HyperlinkedModelSerializer):
class Meta: class Meta:
model = AdoptionNotice model = AdoptionNotice
fields = ['created_at', 'last_checked', "searching_since", "name", "description", "further_information", "group_only"] fields = ['created_at', 'last_checked', "searching_since", "name", "description", "further_information",
"group_only"]
class AnimalCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Animal
fields = ["name", "date_of_birth", "description", "species", "sex", "adoption_notice"]
class AnimalGetSerializer(serializers.ModelSerializer):
class Meta:
model = Animal
fields = "__all__"
class RescueOrganizationSerializer(serializers.ModelSerializer):
class Meta:
model = RescueOrganization
exclude = ["internal_comment", "allows_using_materials"]
class ImageCreateSerializer(serializers.ModelSerializer):
@staticmethod
def _animal_or_an(value):
if not value in ["animal", "adoption_notice"]:
raise serializers.ValidationError(
'Set either animal or adoption_notice, depending on what type of object the image should be attached to.')
attach_to_type = serializers.CharField(validators=[_animal_or_an])
attach_to = serializers.IntegerField()
class Meta:
model = Image
exclude = ["owner"]
class SpeciesSerializer(serializers.ModelSerializer):
class Meta:
model = Species
fields = "__all__"

View File

@ -1,8 +1,16 @@
from django.urls import path from django.urls import path
from .views import ( from .views import (
AdoptionNoticeApiView AdoptionNoticeApiView,
AnimalApiView, RescueOrganizationApiView, AddImageApiView, SpeciesApiView
) )
urlpatterns = [ urlpatterns = [
path('adoption_notice', AdoptionNoticeApiView.as_view()), path("adoption_notice", AdoptionNoticeApiView.as_view(), name="api-adoption-notice-list"),
path("adoption_notice/<int:id>/", AdoptionNoticeApiView.as_view(), name="api-adoption-notice-detail"),
path("animals/", AnimalApiView.as_view(), name="api-animal-list"),
path("animals/<int:id>/", AnimalApiView.as_view(), name="api-animal-detail"),
path("organizations/", RescueOrganizationApiView.as_view(), name="api-organization-list"),
path("organizations/<int:id>/", RescueOrganizationApiView.as_view(), name="api-organization-detail"),
path("images/", AddImageApiView.as_view(), name="api-add-image"),
path("species/", SpeciesApiView.as_view(), name="api-species-list"),
] ]

View File

@ -7,18 +7,36 @@ from rest_framework.permissions import IsAuthenticated
from django.db import transaction from django.db import transaction
from fellchensammlung.models import AdoptionNotice, Animal, Log, TrustLevel from fellchensammlung.models import AdoptionNotice, Animal, Log, TrustLevel
from fellchensammlung.tasks import add_adoption_notice_location from fellchensammlung.tasks import add_adoption_notice_location
from .serializers import AdoptionNoticeSerializer from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from .serializers import (
AnimalGetSerializer,
AnimalCreateSerializer,
RescueOrganizationSerializer,
AdoptionNoticeSerializer,
ImageCreateSerializer,
SpeciesSerializer,
)
from fellchensammlung.models import Animal, RescueOrganization, AdoptionNotice, Species, Image
class AdoptionNoticeApiView(APIView): class AdoptionNoticeApiView(APIView):
permission_classes = [permissions.IsAuthenticated] permission_classes = [IsAuthenticated]
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
serializer_context = { """
'request': request, Retrieve adoption notices with their related animals and images.
} """
adoption_notice_id = kwargs.get("id")
if adoption_notice_id:
try:
adoption_notice = AdoptionNotice.objects.get(pk=adoption_notice_id)
serializer = AdoptionNoticeSerializer(adoption_notice, context={"request": request})
return Response(serializer.data, status=status.HTTP_200_OK)
except AdoptionNotice.DoesNotExist:
return Response({"error": "Adoption notice not found."}, status=status.HTTP_404_NOT_FOUND)
adoption_notices = AdoptionNotice.objects.all() adoption_notices = AdoptionNotice.objects.all()
serializer = AdoptionNoticeSerializer(adoption_notices, many=True, context=serializer_context) serializer = AdoptionNoticeSerializer(adoption_notices, many=True, context={"request": request})
return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.data, status=status.HTTP_200_OK)
@transaction.atomic @transaction.atomic
@ -53,3 +71,96 @@ class AdoptionNoticeApiView(APIView):
{"message": "Adoption notice created successfully!", "id": adoption_notice.pk}, {"message": "Adoption notice created successfully!", "id": adoption_notice.pk},
status=status.HTTP_201_CREATED, status=status.HTTP_201_CREATED,
) )
class AnimalApiView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request, *args, **kwargs):
"""
Get list of animals or a specific animal by ID.
"""
animal_id = kwargs.get("id")
if animal_id:
try:
animal = Animal.objects.get(pk=animal_id)
serializer = AnimalGetSerializer(animal, context={"request": request})
return Response(serializer.data, status=status.HTTP_200_OK)
except Animal.DoesNotExist:
return Response({"error": "Animal not found."}, status=status.HTTP_404_NOT_FOUND)
animals = Animal.objects.all()
serializer = AnimalGetSerializer(animals, many=True, context={"request": request})
return Response(serializer.data, status=status.HTTP_200_OK)
@transaction.atomic
def post(self, request, *args, **kwargs):
"""
Create a new animal.
"""
serializer = AnimalCreateSerializer(data=request.data, context={"request": request})
if serializer.is_valid():
animal = serializer.save(owner=request.user)
return Response(
{"message": "Animal created successfully!", "id": animal.id},
status=status.HTTP_201_CREATED,
)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class RescueOrganizationApiView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request, *args, **kwargs):
"""
Get list of rescue organizations or a specific organization by ID.
"""
org_id = kwargs.get("id")
if org_id:
try:
organization = RescueOrganization.objects.get(pk=org_id)
serializer = RescueOrganizationSerializer(organization, context={"request": request})
return Response(serializer.data, status=status.HTTP_200_OK)
except RescueOrganization.DoesNotExist:
return Response({"error": "Organization not found."}, status=status.HTTP_404_NOT_FOUND)
organizations = RescueOrganization.objects.all()
serializer = RescueOrganizationSerializer(organizations, many=True, context={"request": request})
return Response(serializer.data, status=status.HTTP_200_OK)
class AddImageApiView(APIView):
permission_classes = [IsAuthenticated]
@transaction.atomic
def post(self, request, *args, **kwargs):
"""
Add an image to an animal or adoption notice.
"""
serializer = ImageCreateSerializer(data=request.data, context={"request": request})
if serializer.is_valid():
if serializer.validated_data["attach_to_type"] == "animal":
object_to_attach_to = Animal.objects.get(id=serializer.validated_data["attach_to"])
elif serializer.fields["attach_to_type"] == "adoption_notice":
object_to_attach_to = AdoptionNotice.objects.get(id=serializer.validated_data["attach_to"])
else:
raise ValueError("Unknown attach_to_type given, should not happen. Check serializer")
serializer.validated_data.pop('attach_to_type', None)
serializer.validated_data.pop('attach_to', None)
image = serializer.save(owner=request.user)
object_to_attach_to.photos.add(image)
return Response(
{"message": "Image added successfully!", "id": image.id},
status=status.HTTP_201_CREATED,
)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class SpeciesApiView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request, *args, **kwargs):
"""
Retrieve a list of species.
"""
species = Species.objects.all()
serializer = SpeciesSerializer(species, many=True, context={"request": request})
return Response(serializer.data, status=status.HTTP_200_OK)