.
This commit is contained in:
+138
-13
@@ -6084,6 +6084,13 @@ def exam_search_widget(request):
|
||||
except Exception:
|
||||
model = None
|
||||
|
||||
# Helper to parse optional boolean GET params
|
||||
def _get_bool_param(name):
|
||||
v = request.GET.get(name)
|
||||
if v is None:
|
||||
return None
|
||||
return str(v).lower() in ("1", "true", "yes", "on")
|
||||
|
||||
# Build queryset
|
||||
qs = None
|
||||
if model is not None:
|
||||
@@ -6118,20 +6125,34 @@ def exam_search_widget(request):
|
||||
"sbas.Exam",
|
||||
]
|
||||
results = []
|
||||
|
||||
# gather optional filters from GET params
|
||||
extra_filters = {}
|
||||
for pname in ("archive", "open_access", "exam_mode", "candidates_only"):
|
||||
val = _get_bool_param(pname)
|
||||
if val is not None:
|
||||
extra_filters[pname] = val
|
||||
|
||||
for ml in possible_models:
|
||||
try:
|
||||
m = apps.get_model(*ml.split("."))
|
||||
except Exception:
|
||||
continue
|
||||
try:
|
||||
rqs = m.objects.filter(name__icontains=q)[:5]
|
||||
except Exception:
|
||||
# try common name-like fields and apply extra_filters when possible
|
||||
try:
|
||||
rqs = m.objects.filter(title__icontains=q)[:5]
|
||||
rqs = m.objects.filter(name__icontains=q, **extra_filters)[:5]
|
||||
except Exception:
|
||||
rqs = m.objects.none()
|
||||
try:
|
||||
rqs = m.objects.filter(title__icontains=q, **extra_filters)[:5]
|
||||
except Exception:
|
||||
# fallback to unfiltered small slice
|
||||
rqs = m.objects.filter(name__icontains=q)[:5]
|
||||
except Exception:
|
||||
rqs = m.objects.none()
|
||||
for o in rqs:
|
||||
results.append(o)
|
||||
|
||||
# Render combined results, but restrict to exams the user can access
|
||||
def user_can_view_exam(exam, user):
|
||||
try:
|
||||
@@ -6160,7 +6181,14 @@ def exam_search_widget(request):
|
||||
rendered_results = []
|
||||
for o in results[:50]:
|
||||
if user_can_view_exam(o, request.user):
|
||||
rendered_results.append({"id": getattr(o, "pk", None), "text": str(o)})
|
||||
rendered_results.append({
|
||||
"id": getattr(o, "pk", None),
|
||||
"text": str(o),
|
||||
"archive": getattr(o, "archive", False),
|
||||
"open_access": getattr(o, "open_access", False),
|
||||
"exam_mode": getattr(o, "exam_mode", False),
|
||||
"candidates_only": getattr(o, "candidates_only", False),
|
||||
})
|
||||
return render(request, "generic/partials/exam_search_widget_results.html", {"results": rendered_results, "field": field, "q": q_raw})
|
||||
|
||||
# Limit results
|
||||
@@ -6200,10 +6228,36 @@ def exam_search_widget(request):
|
||||
pass
|
||||
return False
|
||||
|
||||
# Apply optional filters from GET params to the per-model queryset
|
||||
extra_filters = {}
|
||||
for pname in ("archive", "open_access", "exam_mode", "candidates_only"):
|
||||
val = _get_bool_param(pname)
|
||||
if val is not None:
|
||||
extra_filters[pname] = val
|
||||
|
||||
results = []
|
||||
for e in qs:
|
||||
# apply any extra_filters defensively (models may not have fields)
|
||||
skip = False
|
||||
for k, v in extra_filters.items():
|
||||
try:
|
||||
if getattr(e, k, None) != v:
|
||||
skip = True
|
||||
break
|
||||
except Exception:
|
||||
# if attribute access fails, don't skip
|
||||
continue
|
||||
if skip:
|
||||
continue
|
||||
if user_can_view_exam(e, request.user):
|
||||
results.append({"id": e.pk, "text": str(e)})
|
||||
results.append({
|
||||
"id": e.pk,
|
||||
"text": str(e),
|
||||
"archive": getattr(e, "archive", False),
|
||||
"open_access": getattr(e, "open_access", False),
|
||||
"exam_mode": getattr(e, "exam_mode", False),
|
||||
"candidates_only": getattr(e, "candidates_only", False),
|
||||
})
|
||||
|
||||
return render(request, "generic/partials/exam_search_widget_results.html", {"results": results, "field": field, "q": q_raw})
|
||||
|
||||
@@ -6223,14 +6277,85 @@ def supervisor_search(request):
|
||||
q = (request.GET.get("q") or "").strip()
|
||||
row = request.GET.get("row")
|
||||
if not q:
|
||||
return HttpResponse("")
|
||||
else:
|
||||
# If no model specified, try to search across several known exam models
|
||||
possible_models = [
|
||||
"anatomy.Exam",
|
||||
"longs.Exam",
|
||||
"rapids.Exam",
|
||||
"shorts.Exam",
|
||||
"physics.Exam",
|
||||
"sbas.Exam",
|
||||
]
|
||||
results = []
|
||||
|
||||
supervisors_qs = Supervisor.objects.filter(
|
||||
Q(name__icontains=q) | Q(email__icontains=q)
|
||||
).order_by("name")[:10]
|
||||
# gather optional filters from GET params
|
||||
extra_filters = {}
|
||||
for pname in ("archive", "open_access", "exam_mode", "candidates_only"):
|
||||
val = _get_bool_param(pname)
|
||||
if val is not None:
|
||||
extra_filters[pname] = val
|
||||
|
||||
results = [{"id": s.pk, "text": f"{s.name} - {s.email or ''}"} for s in supervisors_qs]
|
||||
for ml in possible_models:
|
||||
try:
|
||||
m = apps.get_model(*ml.split("."))
|
||||
except Exception:
|
||||
continue
|
||||
try:
|
||||
# try common name-like fields and apply extra_filters when possible
|
||||
try:
|
||||
rqs = m.objects.filter(name__icontains=q, **extra_filters)[:5]
|
||||
except Exception:
|
||||
try:
|
||||
rqs = m.objects.filter(title__icontains=q, **extra_filters)[:5]
|
||||
except Exception:
|
||||
# fallback to unfiltered small slice
|
||||
rqs = m.objects.filter(name__icontains=q)[:5]
|
||||
except Exception:
|
||||
rqs = m.objects.none()
|
||||
for o in rqs:
|
||||
results.append(o)
|
||||
|
||||
return render(request, "generic/partials/supervisor_search_results.html", {"results": results, "row": row, "q": q})
|
||||
# Render combined results, but restrict to exams the user can access
|
||||
def user_can_view_exam(exam, user):
|
||||
try:
|
||||
if user.is_superuser:
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
if getattr(exam, "open_access", False) and getattr(exam, "active", False):
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
authors = exam.get_author_objects()
|
||||
if user in authors:
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
if hasattr(exam, "cid_user_exam") and exam.cid_user_exam.filter(user_user=user).exists():
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
if hasattr(exam, "markers") and user in exam.markers.all():
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
return False
|
||||
|
||||
rendered_results = []
|
||||
for o in results[:50]:
|
||||
if user_can_view_exam(o, request.user):
|
||||
rendered_results.append({
|
||||
"id": getattr(o, "pk", None),
|
||||
"text": str(o),
|
||||
"archive": getattr(o, "archive", False),
|
||||
"open_access": getattr(o, "open_access", False),
|
||||
"exam_mode": getattr(o, "exam_mode", False),
|
||||
"candidates_only": getattr(o, "candidates_only", False),
|
||||
})
|
||||
return render(request, "generic/partials/exam_search_widget_results.html", {"results": rendered_results, "field": field, "q": q_raw})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user