from django.urls import re_path from django.contrib.auth.decorators import permission_required from rest_framework import routers, viewsets from rest_framework.decorators import api_view, permission_classes from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated from inventory.models import Event, Container, Item from inventory.serializers import EventSerializer, ContainerSerializer, ItemSerializer, SearchResultSerializer from base64 import b64decode class EventViewSet(viewsets.ModelViewSet): serializer_class = EventSerializer queryset = Event.objects.all() permission_classes = [] class ContainerViewSet(viewsets.ModelViewSet): serializer_class = ContainerSerializer queryset = Container.objects.all() def filter_items(items, query): query_tokens = query.split(' ') for item in items: value = 0 for token in query_tokens: if token in item.description: value += 1 if value > 0: yield {'search_score': value, 'item': item} @api_view(['GET']) @permission_classes([IsAuthenticated]) def search_items(request, event_slug, query): try: event = Event.objects.get(slug=event_slug) if not request.user.has_event_perm(event, 'view_item'): return Response(status=403) items = filter_items(Item.objects.filter(event=event), b64decode(query).decode('utf-8')) return Response(SearchResultSerializer(items, many=True).data) except Event.DoesNotExist: return Response(status=404) @api_view(['GET', 'POST']) @permission_classes([IsAuthenticated]) def item(request, event_slug): try: event = None if event_slug != 'none': event = Event.objects.get(slug=event_slug) if request.method == 'GET': if not request.user.has_event_perm(event, 'view_item'): return Response(status=403) return Response(ItemSerializer(Item.objects.filter(event=event), many=True).data) elif request.method == 'POST': if not request.user.has_event_perm(event, 'add_item'): return Response(status=403) validated_data = ItemSerializer(data=request.data) if validated_data.is_valid(): validated_data.save(event=event) return Response(validated_data.data, status=201) return Response(status=400) except Event.DoesNotExist: return Response(status=404) except KeyError: return Response(status=400) @api_view(['GET', 'PUT', 'DELETE', 'PATCH']) @permission_classes([IsAuthenticated]) def item_by_id(request, event_slug, id): try: event = Event.objects.get(slug=event_slug) item = Item.objects.get(event=event, id=id) if request.method == 'GET': if not request.user.has_event_perm(event, 'view_item'): return Response(status=403) return Response(ItemSerializer(item).data) elif request.method == 'PUT': if not request.user.has_event_perm(event, 'change_item'): return Response(status=403) validated_data = ItemSerializer(item, data=request.data) if validated_data.is_valid(): validated_data.save() return Response(validated_data.data) return Response(validated_data.errors, status=400) elif request.method == 'PATCH': if not request.user.has_event_perm(event, 'change_item'): return Response(status=403) validated_data = ItemSerializer(item, data=request.data, partial=True) if validated_data.is_valid(): validated_data.save() return Response(validated_data.data) return Response(validated_data.errors, status=400) elif request.method == 'DELETE': if not request.user.has_event_perm(event, 'delete_item'): return Response(status=403) item.delete() return Response(status=204) except Item.DoesNotExist: return Response(status=404) except Event.DoesNotExist: return Response(status=404) router = routers.SimpleRouter() router.register(r'events', EventViewSet, basename='events') router.register(r'boxes', ContainerViewSet, basename='boxes') router.register(r'box', ContainerViewSet, basename='boxes') urlpatterns = router.urls + [ # path('/items/', item), # path('/items//', search_items), # path('/item/', item), # path('/item//', item_by_id), re_path(r'^(?P[\w-]+)/items/$', item, name='item'), re_path(r'^(?P[\w-]+)/items/(?P[-A-Za-z0-9+/]*={0,3})/$', search_items, name='search_items'), re_path(r'^(?P[\w-]+)/item/$', item, name='item'), re_path(r'^(?P[\w-]+)/item/(?P\d+)/$', item_by_id, name='item_by_id'), ]