import bleach import os from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.shortcuts import redirect from django.db.models import F from django.views.generic import DetailView from tickets.forms import TicketForm from tickets.models import Attachment, Comment, Ticket from tickets.utils import UserCanReadTicketMixin class TicketDetailView(LoginRequiredMixin, UserCanReadTicketMixin, DetailView): model = Ticket template_name = 'tickets/ticket_detail.html' context_object_name = 'ticket' def get_queryset(self): queryset = super().get_queryset() return queryset.select_related("created_by", "assigned_to") def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['form'] = TicketForm(self.request.user, instance=self.object) context['comment_list'] = Comment.objects.filter(ticket=self.object.pk).order_by("-date").annotate( author_username=F("author__username"), author_email=F("author__email") ) context['attachments'] = Attachment.objects.filter(ticket=self.object.pk).select_related("added_by") # List with statuses codes & their names available_statuses_with_names = [] available_statuses = self.object.get_available_statuses() if available_statuses: for status_code in available_statuses: status_name = Ticket.TICKET_STATUSES_NAMES.get(status_code) available_statuses_with_names.append([status_code, status_name]) context["available_statuses"] = available_statuses_with_names return context def post(self, request, *args, **kwargs): ticket = self.get_object() if request.POST.get("ticket-status"): status = request.POST.get("ticket-status") if int(status) in ticket.get_available_statuses(): ticket.status = int(status) ticket.save() messages.success(request, f"Status successfully changed.") else: messages.error(request, f"Status change error.") if request.POST.get("comment-body"): Comment.objects.create( author=request.user, ticket=ticket, body=bleach.clean(request.POST.get("comment-body"), strip=True) ) messages.success(request, "Comment posted. Notification email sent to thread participants.") if request.FILES.get("attachment_file_input"): uploaded_file = request.FILES.get("attachment_file_input") name, extension = os.path.splitext(uploaded_file.name) if uploaded_file.size > 5000000: messages.error(request, f"File exceeds maximum attachment size.") elif extension not in [".jpg", ".gif", ".png", ".csv", ".pdf", ".zip", ".txt"]: messages.error(request, f"This site does not allow upload of {extension} files.") else: Attachment.objects.create(ticket=ticket, added_by=request.user, file=uploaded_file) messages.success(request, f"File attached successfully.") return redirect("tickets:ticket_detail", pk=ticket.pk)