Working on Ticket API
Improved filters and added TicketCount API View.
This commit is contained in:
parent
a20fba656a
commit
a708a8b151
@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from .views import TicketListApiView
|
from .views import TicketListApiView, FilterCountApiView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("ticket/", TicketListApiView.as_view(), name="ticket"),
|
path("ticket/", TicketListApiView.as_view(), name="ticket"),
|
||||||
|
path("filter-counts/", FilterCountApiView.as_view(), name="filter-counts"),
|
||||||
]
|
]
|
@ -1,37 +1,60 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
import json
|
import logging
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from django.conf import settings
|
from django.db.models import Q
|
||||||
|
from django.http import HttpRequest
|
||||||
|
from django.core.cache import cache
|
||||||
|
from django.views.decorators.cache import cache_page
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework import status, permissions
|
from rest_framework import status, permissions
|
||||||
|
from rest_framework.pagination import PageNumberPagination
|
||||||
|
|
||||||
from apps.home.models import Ticket, TicketPriority, TicketTag
|
from apps.home.models import Ticket, TicketPriority, TicketTag
|
||||||
|
from apps.authentication.models import Department
|
||||||
from .serializers import (
|
from .serializers import (
|
||||||
TicketSerializer, TicketTagSerializer, TicketPrioritySerializer,
|
TicketSerializer, TicketTagSerializer, TicketPrioritySerializer,
|
||||||
UserSerializer
|
UserSerializer
|
||||||
)
|
)
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def respond_error(error: Exception, status: Any) -> Response:
|
||||||
|
logging.error(error)
|
||||||
|
return Response({
|
||||||
|
"detail": str(error),
|
||||||
|
"error": error.__class__.__name__
|
||||||
|
}, status=status)
|
||||||
|
|
||||||
|
|
||||||
|
class TicketPaginiation(PageNumberPagination):
|
||||||
|
page_size = 25
|
||||||
|
page_size_query_param = "page_size"
|
||||||
|
max_page_size = 100
|
||||||
|
|
||||||
|
|
||||||
class TicketListApiView(APIView):
|
class TicketListApiView(APIView):
|
||||||
permission_classes = [permissions.IsAuthenticated]
|
permission_classes = [permissions.IsAuthenticated]
|
||||||
|
pagination_class = TicketPaginiation
|
||||||
|
|
||||||
def get(self, request):
|
ALLOWED_FILTERS = ("uuid__in", "priority__in", "tags__in", "author__department__in")
|
||||||
"""Return all tickets."""
|
|
||||||
|
|
||||||
filters = json.loads(request.GET.get("filters", "{}"))
|
# @method_decorator(cache_page(60 * 5))
|
||||||
queryset = Ticket.objects.all()
|
def get(self, request: HttpRequest) -> Response:
|
||||||
|
"""Returns a response containing tickets matching the given filters."""
|
||||||
|
|
||||||
for key, values in filters.items():
|
try:
|
||||||
|
return self._get_tickets(request)
|
||||||
for value in values:
|
|
||||||
if value == "all": continue
|
|
||||||
queryset = queryset.filter(**{key: [value]})
|
|
||||||
|
|
||||||
tickets = queryset.order_by("-create_timestamp")
|
except KeyError as error:
|
||||||
serializer = TicketSerializer(tickets, many=True)
|
return respond_error(error, status.HTTP_400_BAD_REQUEST)
|
||||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
|
||||||
|
except ValidationError as error:
|
||||||
|
return respond_error(error, status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
"""Create a new ticket"""
|
"""Create a new ticket"""
|
||||||
@ -40,7 +63,80 @@ class TicketListApiView(APIView):
|
|||||||
|
|
||||||
})
|
})
|
||||||
if not serializer.is_valid():
|
if not serializer.is_valid():
|
||||||
return Response(serlializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
serializer.save()
|
serializer.save()
|
||||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_tickets(self, request: HttpRequest) -> Response:
|
||||||
|
"""Returns a response containing tickets matching the given filters.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
request : HttpRequest
|
||||||
|
The request containing the filters.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Response
|
||||||
|
A response containing the tickets data.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
KeyError
|
||||||
|
If any given filter key isn't in `self.ALLOWED_FILTERS`.
|
||||||
|
ValidationError
|
||||||
|
If any ValidationErrors are raised by Django while applying filters.
|
||||||
|
"""
|
||||||
|
|
||||||
|
queryset = Ticket.objects.all()
|
||||||
|
|
||||||
|
for key in request.GET.keys():
|
||||||
|
values = request.GET.getlist(key) if key.endswith("[]") else [request.GET.get(key)]
|
||||||
|
key = key.removesuffix("[]")
|
||||||
|
|
||||||
|
if key not in self.ALLOWED_FILTERS:
|
||||||
|
raise KeyError(key)
|
||||||
|
|
||||||
|
for value in values:
|
||||||
|
if value == "all": continue
|
||||||
|
queryset = queryset.filter(Q(**{key: [value]}))
|
||||||
|
|
||||||
|
tickets = queryset.order_by("-create_timestamp")
|
||||||
|
serializer = TicketSerializer(tickets, many=True)
|
||||||
|
response_data = serializer.data
|
||||||
|
|
||||||
|
log.debug("Query successful showing %s results", tickets.count())
|
||||||
|
return Response(response_data, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
|
class FilterCountApiView(APIView):
|
||||||
|
permission_classes = [permissions.IsAuthenticated]
|
||||||
|
|
||||||
|
@method_decorator(cache_page(60 * 5))
|
||||||
|
def get(self, request):
|
||||||
|
|
||||||
|
priorities = TicketPriority.objects.all()
|
||||||
|
tags = TicketTag.objects.all()
|
||||||
|
departments = Department.objects.all()
|
||||||
|
|
||||||
|
tickets = Ticket.objects.all()
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"priority_counts": {},
|
||||||
|
"tag_counts": {},
|
||||||
|
"department_counts": {},
|
||||||
|
"ticket_count": tickets.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
for priority in priorities:
|
||||||
|
data["priority_counts"][str(priority.uuid)] = tickets.filter(priority=priority).count()
|
||||||
|
|
||||||
|
for tag in tags:
|
||||||
|
data["tag_counts"][str(tag.uuid)] = tickets.filter(tags__in=[tag]).count()
|
||||||
|
|
||||||
|
for department in departments:
|
||||||
|
data["department_counts"][str(department.uuid)] = tickets.filter(author__department=department).count()
|
||||||
|
|
||||||
|
return Response(data, status=status.HTTP_200_OK)
|
Loading…
x
Reference in New Issue
Block a user