.
This commit is contained in:
@@ -396,7 +396,6 @@ class Exam(ExamBase):
|
|||||||
markers = models.ManyToManyField(
|
markers = models.ManyToManyField(
|
||||||
settings.AUTH_USER_MODEL,
|
settings.AUTH_USER_MODEL,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
|
||||||
help_text="Authorised markers for the exam",
|
help_text="Authorised markers for the exam",
|
||||||
related_name="anatomy_exam_markers",
|
related_name="anatomy_exam_markers",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -796,7 +796,6 @@ class CaseCollection(ExamOrCollectionGenericBase):
|
|||||||
markers = models.ManyToManyField(
|
markers = models.ManyToManyField(
|
||||||
settings.AUTH_USER_MODEL,
|
settings.AUTH_USER_MODEL,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
|
||||||
help_text="Authorised markers for the exam",
|
help_text="Authorised markers for the exam",
|
||||||
related_name="casecollection_markers",
|
related_name="casecollection_markers",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -449,7 +449,6 @@ class Exam(ExamBase):
|
|||||||
markers = models.ManyToManyField(
|
markers = models.ManyToManyField(
|
||||||
settings.AUTH_USER_MODEL,
|
settings.AUTH_USER_MODEL,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
|
||||||
help_text="Authorised markers for the exam",
|
help_text="Authorised markers for the exam",
|
||||||
related_name="long_exam_markers",
|
related_name="long_exam_markers",
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ class Entry(models.Model):
|
|||||||
return self.exam_name
|
return self.exam_name
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("oef:entry_update", kwargs={"pk": self.pk})
|
return reverse("oef:entry_detail", kwargs={"pk": self.pk})
|
||||||
|
|
||||||
def clean(self) -> None:
|
def clean(self) -> None:
|
||||||
self.questions = self.questions.replace("\r\n", "\n")
|
self.questions = self.questions.replace("\r\n", "\n")
|
||||||
|
|||||||
@@ -6,4 +6,5 @@
|
|||||||
{% block navigation %}
|
{% block navigation %}
|
||||||
<a href="{% url 'oef:entry_table_view' %}">Entries</a> /
|
<a href="{% url 'oef:entry_table_view' %}">Entries</a> /
|
||||||
<a href="{% url 'oef:formats_view' %}">Formats</a> /
|
<a href="{% url 'oef:formats_view' %}">Formats</a> /
|
||||||
|
<a href="{% url 'oef:replace_questions' %}">Replace Questions</a> /
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
The following formats match:<br/>
|
||||||
|
{% for format in matching_formats %}
|
||||||
|
<h3>Format: {{ format.name }}</h3>
|
||||||
|
<pre>
|
||||||
|
{{ format.get_format }}
|
||||||
|
</pre>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{% extends 'oef/base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{{ entry.name }}</h1>
|
||||||
|
<a href="{% url 'oef:entry_update' entry.pk %}">Edit</a>
|
||||||
|
|
||||||
|
<p>Modality: {{ entry.modality }}</p>
|
||||||
|
<p>Exam code: {{ entry.exam_code }}</p>
|
||||||
|
|
||||||
|
<p>Questions:
|
||||||
|
<pre>
|
||||||
|
{{ entry.questions }}
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Comments: {{ entry.comments }}</p>
|
||||||
|
|
||||||
|
|
||||||
|
<button
|
||||||
|
hx-get="{% url 'oef:entry_detail_formats' entry.pk %}"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
>Check formats</button>
|
||||||
|
{% endblock content %}
|
||||||
@@ -14,7 +14,7 @@ The format {{format.name}} exists in the following {{ entries.count }} entries:
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
{% for entry, text in entry_list %}
|
{% for entry, text in entry_list %}
|
||||||
<li class=" {% if not text %}no-extra{% endif %}">{{ entry.exam_name }} (<a href='{% url "oef:entry_update" entry.pk %}'>edit</a>)<br/> <pre>{{text}}<pre></li>
|
<li class=" {% if not text %}no-extra{% endif %}">{{ entry.exam_name }} (<a href='{% url "oef:entry_detail" entry.pk %}'>view</a>) (<a href='{% url "oef:entry_update" entry.pk %}'>edit</a>)<br/> <pre>{{text}}<pre></li>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{% extends 'oef/base.html' %}
|
||||||
|
{% block content %}
|
||||||
|
<form>
|
||||||
|
|
||||||
|
<textarea id="search" name="search" placeholder="Search text.."></textarea>
|
||||||
|
<textarea id="replace" name="replace" placeholder="Replace text.."></textarea>
|
||||||
|
<button hx-post="{% url 'oef:replace_questions' %}"
|
||||||
|
hx-target='#result'>Replace</button>
|
||||||
|
<div id="result"></div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock content %}
|
||||||
@@ -20,9 +20,18 @@ urlpatterns = [
|
|||||||
path(
|
path(
|
||||||
"formats/create", views.FormatsCreateView.as_view(), name="format_create"
|
"formats/create", views.FormatsCreateView.as_view(), name="format_create"
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"entries/replace_questions", views.replace_questions, name="replace_questions"
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"entries/<int:pk>/update", views.EntryUpdateView.as_view(), name="entry_update"
|
"entries/<int:pk>/update", views.EntryUpdateView.as_view(), name="entry_update"
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"entries/<int:pk>/detail", views.EntryDetailView.as_view(), name="entry_detail"
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"entries/<int:pk>/detail/formats", views.entry_detail_formats, name="entry_detail_formats"
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"formats/<int:pk>/update", views.FormatsUpdateView.as_view(), name="format_update"
|
"formats/<int:pk>/update", views.FormatsUpdateView.as_view(), name="format_update"
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
from django.http import HttpResponse
|
||||||
from django.shortcuts import get_object_or_404, render
|
from django.shortcuts import get_object_or_404, render
|
||||||
from django.views.generic.edit import UpdateView, CreateView
|
from django.views.generic.edit import UpdateView, CreateView
|
||||||
|
from django.views.generic.detail import DetailView
|
||||||
|
|
||||||
from .models import Entry, Formats
|
from .models import Entry, Formats
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
@@ -14,6 +16,10 @@ class EntryUpdateView(UpdateView):
|
|||||||
template_name = "oef/entry_update_view.html"
|
template_name = "oef/entry_update_view.html"
|
||||||
fields = ['modality', 'exam_code', 'exam_name', 'questions', 'comments']
|
fields = ['modality', 'exam_code', 'exam_name', 'questions', 'comments']
|
||||||
|
|
||||||
|
class EntryDetailView(DetailView):
|
||||||
|
model = Entry
|
||||||
|
template_name = "oef/entry_detail_view.html"
|
||||||
|
|
||||||
class FormatsCreateView(CreateView):
|
class FormatsCreateView(CreateView):
|
||||||
model = Formats
|
model = Formats
|
||||||
template_name_suffix = "_update_form"
|
template_name_suffix = "_update_form"
|
||||||
@@ -47,3 +53,36 @@ def formats_apply(request, pk):
|
|||||||
for entry in entries:
|
for entry in entries:
|
||||||
entry_list.append((entry, entry.questions.replace(search_text, "")))
|
entry_list.append((entry, entry.questions.replace(search_text, "")))
|
||||||
return render(request, "oef/formats_apply.html", {"format": format, "entry_list": entry_list, "entries": entries})
|
return render(request, "oef/formats_apply.html", {"format": format, "entry_list": entry_list, "entries": entries})
|
||||||
|
|
||||||
|
def entry_detail_formats(request, pk):
|
||||||
|
entry = get_object_or_404(Entry, pk=pk)
|
||||||
|
formats = Formats.objects.all()
|
||||||
|
|
||||||
|
questions = entry.questions
|
||||||
|
|
||||||
|
matching_formats = []
|
||||||
|
for format in formats:
|
||||||
|
if format.get_format() in questions:
|
||||||
|
matching_formats.append(format)
|
||||||
|
|
||||||
|
matching_formats = sorted(matching_formats, key=lambda x: len(x.get_format()))
|
||||||
|
|
||||||
|
return render(request, "oef/entry_detail_formats.html", {"entry": entry, "matching_formats": matching_formats})
|
||||||
|
|
||||||
|
def replace_questions(request):
|
||||||
|
if request.method == "POST":
|
||||||
|
search = request.POST.get("search")
|
||||||
|
replace = request.POST.get("replace")
|
||||||
|
|
||||||
|
if not search or not replace:
|
||||||
|
return HttpResponse("Please provide both search and replace values")
|
||||||
|
|
||||||
|
entries = Entry.objects.filter(questions__contains=search)
|
||||||
|
|
||||||
|
for entry in entries:
|
||||||
|
entry.questions = entry.questions.replace(search, replace)
|
||||||
|
entry.save()
|
||||||
|
|
||||||
|
return HttpResponse(f"{entries.count()} questions replaced")
|
||||||
|
else:
|
||||||
|
return render(request, "oef/replace_questions.html", {})
|
||||||
@@ -170,7 +170,6 @@ class Exam(ExamBase):
|
|||||||
markers = models.ManyToManyField(
|
markers = models.ManyToManyField(
|
||||||
settings.AUTH_USER_MODEL,
|
settings.AUTH_USER_MODEL,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
|
||||||
help_text="Authorised markers for the exam",
|
help_text="Authorised markers for the exam",
|
||||||
related_name="physics_exam_markers",
|
related_name="physics_exam_markers",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -632,7 +632,6 @@ class Exam(ExamBase):
|
|||||||
markers = models.ManyToManyField(
|
markers = models.ManyToManyField(
|
||||||
settings.AUTH_USER_MODEL,
|
settings.AUTH_USER_MODEL,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
|
||||||
help_text="Authorised markers for the exam",
|
help_text="Authorised markers for the exam",
|
||||||
related_name="rapid_exam_markers",
|
related_name="rapid_exam_markers",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -188,7 +188,6 @@ class Exam(ExamBase):
|
|||||||
markers = models.ManyToManyField(
|
markers = models.ManyToManyField(
|
||||||
settings.AUTH_USER_MODEL,
|
settings.AUTH_USER_MODEL,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
|
||||||
help_text="Authorised markers for the exam",
|
help_text="Authorised markers for the exam",
|
||||||
related_name="sba_exam_markers",
|
related_name="sba_exam_markers",
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user