from django.utils import timezone from django.urls import re_path from rest_framework import routers, viewsets, serializers from rest_framework.decorators import api_view, permission_classes, authentication_classes from rest_framework.response import Response from files.models import File from inventory.models import Event, Container, Item from inventory.serializers import EventSerializer, ContainerSerializer class EventViewSet(viewsets.ModelViewSet): serializer_class = EventSerializer queryset = Event.objects.all() permission_classes = [] authentication_classes = [] class ContainerViewSet(viewsets.ModelViewSet): serializer_class = ContainerSerializer queryset = Container.objects.all() permission_classes = [] authentication_classes = [] class ItemSerializer(serializers.ModelSerializer): dataImage = serializers.CharField(write_only=True, required=False) cid = serializers.SerializerMethodField() box = serializers.SerializerMethodField() file = serializers.SerializerMethodField() class Meta: model = Item fields = ['cid', 'box', 'uid', 'description', 'file', 'dataImage'] read_only_fields = ['uid'] def get_cid(self, instance): return instance.container.cid def get_box(self, instance): return instance.container.name def get_file(self, instance): if len(instance.files.all()) > 0: return instance.files.all().order_by('-created_at')[0].hash return None def to_internal_value(self, data): if 'cid' in data: container = Container.objects.get(cid=data['cid']) internal = super().to_internal_value(data) internal['container'] = container return internal return super().to_internal_value(data) def validate(self, attrs): return super().validate(attrs) def create(self, validated_data): if 'dataImage' in validated_data: file = File.objects.create(data=validated_data['dataImage']) validated_data.pop('dataImage') item = Item.objects.create(**validated_data) item.files.set([file]) return item return Item.objects.create(**validated_data) def update(self, instance, validated_data): if 'returned' in validated_data: if validated_data['returned']: validated_data['returned_at'] = timezone.now() validated_data.pop('returned') if 'dataImage' in validated_data: file = File.objects.create(data=validated_data['dataImage']) validated_data.pop('dataImage') instance.files.add(file) return super().update(instance, validated_data) @api_view(['GET']) @permission_classes([]) @authentication_classes([]) def search_items(request, event_slug, query): try: event = Event.objects.get(slug=event_slug) query_tokens = query.split(' ') q = Item.objects.filter(event=event) for token in query_tokens: if token: q = q.filter(description__icontains=token) return Response(ItemSerializer(q, many=True).data) except Event.DoesNotExist: return Response(status=404) @api_view(['GET', 'POST']) @permission_classes([]) @authentication_classes([]) def item(request, event_slug): try: event = Event.objects.get(slug=event_slug) if request.method == 'GET': return Response(ItemSerializer(Item.objects.filter(event=event), many=True).data) elif request.method == 'POST': validated_data = ItemSerializer(data=request.data) if validated_data.is_valid(): validated_data.save(event=event) return Response(validated_data.data, status=201) except Event.DoesNotExist: return Response(status=404) @api_view(['GET', 'PUT', 'DELETE']) @permission_classes([]) @authentication_classes([]) def item_by_id(request, event_slug, id): try: event = Event.objects.get(slug=event_slug) item = Item.objects.get(event=event, uid=id) if request.method == 'GET': return Response(ItemSerializer(item).data) elif request.method == 'PUT': validated_data = ItemSerializer(item, data=request.data) if validated_data.is_valid(): validated_data.save() return Response(validated_data.data) elif request.method == 'DELETE': item.delete() return Response(status=204) except Item.DoesNotExist: return Response(status=404) except Event.DoesNotExist: return Response(status=404) urlpatterns = [ re_path('events/?$', EventViewSet.as_view({'get': 'list', 'post': 'create'})), re_path('events/(?P[0-9]+)/?$', EventViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})), re_path('boxes/?$', ContainerViewSet.as_view({'get': 'list', 'post': 'create'})), re_path('boxes/(?P[0-9]+)/?$', ContainerViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})), re_path('box/?$', ContainerViewSet.as_view({'get': 'list', 'post': 'create'})), re_path('box/(?P[0-9]+)/?$', ContainerViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})), re_path('(?P[a-zA-Z0-9]+)/items/?$', item), re_path('(?P[a-zA-Z0-9]+)/items/(?P[^/]+)/?$', search_items), re_path('(?P[a-zA-Z0-9]+)/item/?$', item), re_path('(?P[a-zA-Z0-9]+)/item/(?P[0-9]+)/?$', item_by_id), ]