NDOJ/judge/views/select2.py
2023-08-24 10:37:04 -05:00

195 lines
5.9 KiB
Python

from urllib.parse import urljoin
from django.db.models import F, Q
from django.http import Http404, JsonResponse
from django.shortcuts import get_object_or_404
from django.utils.encoding import smart_text
from django.views.generic.list import BaseListView
from django.conf import settings
from chat_box.utils import encrypt_url
from judge.jinja2.gravatar import gravatar
from judge.models import Comment, Contest, Organization, Problem, Profile
def _get_user_queryset(term, org_id=None):
if org_id:
try:
qs = Organization.objects.get(id=org_id).members.all()
except Exception:
raise Http404()
else:
qs = Profile.objects
if term.endswith(" "):
qs = qs.filter(user__username=term.strip())
else:
qs = qs.filter(user__username__icontains=term)
return qs
class Select2View(BaseListView):
paginate_by = 20
def get(self, request, *args, **kwargs):
self.request = request
self.term = kwargs.get("term", request.GET.get("term", ""))
self.object_list = self.get_queryset()
context = self.get_context_data()
return JsonResponse(
{
"results": [
{
"text": smart_text(self.get_name(obj)),
"id": obj.pk,
}
for obj in context["object_list"]
],
"more": context["page_obj"].has_next(),
}
)
def get_name(self, obj):
return str(obj)
class UserSelect2View(Select2View):
def get(self, request, *args, **kwargs):
self.org_id = kwargs.get("org_id", request.GET.get("org_id", ""))
return super(UserSelect2View, self).get(request, *args, **kwargs)
def get_queryset(self):
return (
_get_user_queryset(self.term, self.org_id)
.annotate(username=F("user__username"))
.only("id")
)
def get_name(self, obj):
return obj.username
class OrganizationSelect2View(Select2View):
def get_queryset(self):
return Organization.objects.filter(name__icontains=self.term)
class ProblemSelect2View(Select2View):
def get_queryset(self):
return (
Problem.get_visible_problems(self.request.user)
.filter(Q(code__icontains=self.term) | Q(name__icontains=self.term))
.distinct()
)
class ContestSelect2View(Select2View):
def get_queryset(self):
return Contest.get_visible_contests(self.request.user).filter(
Q(key__icontains=self.term) | Q(name__icontains=self.term)
)
class CommentSelect2View(Select2View):
def get_queryset(self):
return Comment.objects.filter(page__icontains=self.term)
class UserSearchSelect2View(BaseListView):
paginate_by = 20
def get_queryset(self):
return _get_user_queryset(self.term)
def get_json_result_from_object(self, user_tuple):
pk, username, email, display_rank, profile_image = user_tuple
return {
"text": username,
"id": username,
"gravatar_url": gravatar(
None,
self.gravatar_size,
self.gravatar_default,
self.get_profile_image_url(profile_image),
email,
),
"display_rank": display_rank,
}
def get(self, request, *args, **kwargs):
self.request = request
self.kwargs = kwargs
self.term = kwargs.get("term", request.GET.get("term", ""))
self.gravatar_size = request.GET.get("gravatar_size", 128)
self.gravatar_default = request.GET.get("gravatar_default", None)
self.object_list = self.get_queryset().values_list(
"pk", "user__username", "user__email", "display_rank", "profile_image"
)
context = self.get_context_data()
return JsonResponse(
{
"results": [
self.get_json_result_from_object(user_tuple)
for user_tuple in context["object_list"]
],
"more": context["page_obj"].has_next(),
}
)
def get_name(self, obj):
return str(obj)
def get_profile_image_url(self, profile_image):
if profile_image:
return urljoin(settings.MEDIA_URL, profile_image)
return None
class ContestUserSearchSelect2View(UserSearchSelect2View):
def get_queryset(self):
contest = get_object_or_404(Contest, key=self.kwargs["contest"])
if not contest.is_accessible_by(
self.request.user
) or not contest.can_see_full_scoreboard(self.request.user):
raise Http404()
return Profile.objects.filter(
contest_history__contest=contest, user__username__icontains=self.term
).distinct()
class TicketUserSelect2View(UserSearchSelect2View):
def get_queryset(self):
return Profile.objects.filter(
tickets__isnull=False, user__username__icontains=self.term
).distinct()
class AssigneeSelect2View(UserSearchSelect2View):
def get_queryset(self):
return Profile.objects.filter(
assigned_tickets__isnull=False, user__username__icontains=self.term
).distinct()
class ChatUserSearchSelect2View(UserSearchSelect2View):
def get_json_result_from_object(self, user_tuple):
if not self.request.user.is_authenticated:
raise Http404()
pk, username, email, display_rank, profile_image = user_tuple
return {
"text": username,
"id": encrypt_url(self.request.profile.id, pk),
"gravatar_url": gravatar(
None,
self.gravatar_size,
self.gravatar_default,
self.get_profile_image_url(profile_image),
email,
),
"display_rank": display_rank,
}