from rest_framework import generics, status from rest_framework.response import Response from django_filters.rest_framework import DjangoFilterBackend from .models import Device from .serializers import ( CreateDeviceSerializer, DeviceSerializer, ReadOnlyDeviceSerializer, ) from api.mixins import StaffEditorPermissionMixin from .filters import DeviceFilter import re class DeviceListCreateAPIView( StaffEditorPermissionMixin, generics.ListCreateAPIView, ): queryset = Device.objects.select_related("user").all() serializer_class = CreateDeviceSerializer filter_backends = [DjangoFilterBackend] filterset_fields = "__all__" filterset_class = DeviceFilter def get_serializer_class(self) -> type: if self.request.method == "POST": return CreateDeviceSerializer return DeviceSerializer # @method_decorator(cache_page(10)) def create(self, request, *args, **kwargs): mac = request.data.get("mac", None) if not re.match(r"^([0-9A-Fa-f]{2}([.:-]?)){5}[0-9A-Fa-f]{2}$", mac): return Response({"message": "Invalid mac address."}, status=400) if Device.objects.filter(mac=mac).exists(): return Response( {"message": "Device with this mac address already exists."}, status=400 ) return super().create(request, *args, **kwargs) def perform_create(self, serializer): serializer.save(user=self.request.user) class DeviceDetailAPIView(StaffEditorPermissionMixin, generics.RetrieveAPIView): queryset = Device.objects.select_related("user").all() serializer_class = ReadOnlyDeviceSerializer lookup_field = "pk" class DeviceUpdateAPIView(StaffEditorPermissionMixin, generics.UpdateAPIView): queryset = Device.objects.all() serializer_class = CreateDeviceSerializer lookup_field = "pk" def update(self, request, *args, **kwargs): # Pass 'partial=True' to allow partial updates partial = kwargs.pop("partial", True) instance = self.get_object() mac = request.data.get("mac", None) if not re.match(r"^([0-9A-Fa-f]{2}([.:-]?)){5}[0-9A-Fa-f]{2}$", mac): return Response({"message": "Invalid mac address"}, status=400) serializer = self.get_serializer(instance, data=request.data, partial=partial) serializer.is_valid(raise_exception=True) self.perform_update(serializer) return Response(serializer.data) class DeviceDestroyAPIView(StaffEditorPermissionMixin, generics.DestroyAPIView): queryset = Device.objects.all() serializer_class = DeviceSerializer lookup_field = "pk" def destroy(self, request, *args, **kwargs): instance = self.get_object() device_name = instance.name self.perform_destroy(instance) return Response( {"message": f"Device '{device_name}' deleted."}, status=status.HTTP_200_OK, )