Refactor exam management: update exam edit form and add exam links partial
This commit is contained in:
+25
-83
@@ -6675,30 +6675,27 @@ def exam_search_widget(request):
|
||||
if v is None:
|
||||
return None
|
||||
return str(v).lower() in ("1", "true", "yes", "on")
|
||||
# Render combined results, but restrict to exams the user can access
|
||||
def user_can_view_exam(exam, user):
|
||||
if user.is_superuser:
|
||||
return True
|
||||
if exam.open_access:
|
||||
return True
|
||||
authors = exam.get_author_objects()
|
||||
if user in authors:
|
||||
return True
|
||||
if hasattr(exam, "markers") and user in exam.markers.all():
|
||||
return True
|
||||
return False
|
||||
|
||||
# Build queryset
|
||||
qs = None
|
||||
if model is not None:
|
||||
# Try common name-like fields for exams
|
||||
from django.db.models import Q
|
||||
|
||||
field_lookups = ["name__icontains", "title__icontains", "examination__icontains", "modality__icontains"]
|
||||
field_lookups = ["name__icontains"]
|
||||
for lookup in field_lookups:
|
||||
try:
|
||||
qs = model.objects.filter(**{lookup: q})
|
||||
if qs.exists():
|
||||
break
|
||||
except Exception:
|
||||
qs = None
|
||||
# fallback: try icontains on str() via name if present
|
||||
if qs is None or not qs.exists():
|
||||
try:
|
||||
qs = model.objects.filter(Q(name__icontains=q) | Q(title__icontains=q))
|
||||
except Exception:
|
||||
try:
|
||||
qs = model.objects.all()
|
||||
except Exception:
|
||||
qs = model.objects.none()
|
||||
qs = model.objects.filter(**{lookup: q})
|
||||
if qs.exists():
|
||||
break
|
||||
else:
|
||||
# If no model specified, try to search across several known exam models
|
||||
possible_models = [
|
||||
@@ -6738,30 +6735,6 @@ def exam_search_widget(request):
|
||||
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:
|
||||
if user.is_superuser:
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
if exam.open_access:
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
authors = exam.get_author_objects()
|
||||
if user in authors:
|
||||
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]:
|
||||
@@ -6776,42 +6749,12 @@ def exam_search_widget(request):
|
||||
})
|
||||
return render(request, "generic/partials/exam_search_widget_results.html", {"results": rendered_results, "field": field, "q": q_raw})
|
||||
|
||||
logger.error(qs)
|
||||
|
||||
# Limit results
|
||||
limit = 50 if q in ("*", "%") else 10
|
||||
try:
|
||||
qs = qs.order_by("name")[:limit]
|
||||
except Exception:
|
||||
qs = qs[:limit]
|
||||
qs = qs.order_by("name")[:limit]
|
||||
|
||||
# Restrict results to exams the requesting 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
|
||||
|
||||
# Apply optional filters from GET params to the per-model queryset
|
||||
extra_filters = {}
|
||||
@@ -6821,17 +6764,14 @@ def exam_search_widget(request):
|
||||
extra_filters[pname] = val
|
||||
|
||||
results = []
|
||||
logger.error(f"Exam search widget: model={model}, q='{q}', extra_filters={extra_filters}, initial_count={qs.count() if qs is not None else 'N/A'}")
|
||||
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 getattr(e, k, None) != v:
|
||||
skip = True
|
||||
break
|
||||
if skip:
|
||||
continue
|
||||
if user_can_view_exam(e, request.user):
|
||||
@@ -6844,6 +6784,8 @@ def exam_search_widget(request):
|
||||
"candidates_only": getattr(e, "candidates_only", False),
|
||||
})
|
||||
|
||||
logger.error(f"Exam search widget: returning {len(results)} results after filtering")
|
||||
|
||||
return render(request, "generic/partials/exam_search_widget_results.html", {"results": results, "field": field, "q": q_raw})
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user