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 .views import TicketListApiView
|
||||
from .views import TicketListApiView, FilterCountApiView
|
||||
|
||||
urlpatterns = [
|
||||
path("ticket/", TicketListApiView.as_view(), name="ticket"),
|
||||
path("filter-counts/", FilterCountApiView.as_view(), name="filter-counts"),
|
||||
]
|
@ -1,37 +1,60 @@
|
||||
# -*- 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.response import Response
|
||||
from rest_framework import status, permissions
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
|
||||
from apps.home.models import Ticket, TicketPriority, TicketTag
|
||||
from apps.authentication.models import Department
|
||||
from .serializers import (
|
||||
TicketSerializer, TicketTagSerializer, TicketPrioritySerializer,
|
||||
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):
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
pagination_class = TicketPaginiation
|
||||
|
||||
def get(self, request):
|
||||
"""Return all tickets."""
|
||||
ALLOWED_FILTERS = ("uuid__in", "priority__in", "tags__in", "author__department__in")
|
||||
|
||||
filters = json.loads(request.GET.get("filters", "{}"))
|
||||
queryset = Ticket.objects.all()
|
||||
# @method_decorator(cache_page(60 * 5))
|
||||
def get(self, request: HttpRequest) -> Response:
|
||||
"""Returns a response containing tickets matching the given filters."""
|
||||
|
||||
for key, values in filters.items():
|
||||
|
||||
for value in values:
|
||||
if value == "all": continue
|
||||
queryset = queryset.filter(**{key: [value]})
|
||||
try:
|
||||
return self._get_tickets(request)
|
||||
|
||||
tickets = queryset.order_by("-create_timestamp")
|
||||
serializer = TicketSerializer(tickets, many=True)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
except KeyError as error:
|
||||
return respond_error(error, status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
except ValidationError as error:
|
||||
return respond_error(error, status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def post(self, request):
|
||||
"""Create a new ticket"""
|
||||
@ -40,7 +63,80 @@ class TicketListApiView(APIView):
|
||||
|
||||
})
|
||||
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()
|
||||
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