add a redirct view mixin

This commit is contained in:
Ross
2024-08-12 11:58:28 +01:00
parent 8beb6890a7
commit c2185f73a6
8 changed files with 126 additions and 106 deletions
+2 -19
View File
@@ -52,7 +52,7 @@ from .models import (
# IncorrectAnswers,
)
from generic.models import CidUser, Examination
from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamCreateBase, ExamDeleteBase, ExamGroupsUpdateBase, ExamUpdateBase, ExamViews, GenericViewBase
from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamCreateBase, ExamDeleteBase, ExamGroupsUpdateBase, ExamUpdateBase, ExamViews, GenericViewBase, UpdateQuestionMixin
from reversion.views import RevisionMixin
from .decorators import user_is_author_or_anatomy_checker
@@ -598,27 +598,10 @@ class AnatomyQuestionAnswerUpdate(RevisionMixin, AuthorOrCheckerRequiredMixin, U
return super().form_invalid(form)
# class AnatomyQuestionUpdate(LoginRequiredMixin, AuthorOrCheckerRequiredMixin,
class AnatomyQuestionUpdate(RevisionMixin, AuthorOrCheckerRequiredMixin, UpdateView):
class AnatomyQuestionUpdate(UpdateQuestionMixin,AuthorOrCheckerRequiredMixin):
model = AnatomyQuestion
form_class = AnatomyQuestionForm
def get_form_kwargs(self):
kwargs = super(AnatomyQuestionUpdate, self).get_form_kwargs()
kwargs.update({"user": self.request.user})
return kwargs
def get_context_data(self, **kwargs):
context = super(AnatomyQuestionUpdate, self).get_context_data(**kwargs)
#if self.request.POST:
# context["answer_formset"] = AnswerUpdateFormSet(
# self.request.POST, self.request.FILES, instance=self.object
# )
# context["answer_formset"].full_clean()
#else:
# context["answer_formset"] = AnswerUpdateFormSet(instance=self.object)
context["question"] = context["object"]
return context
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.save()
+10
View File
@@ -186,6 +186,16 @@ class QuestionBase(models.Model, AuthorMixin, QuestionMixin):
"""If this makes sense in the question/answer context override"""
return None
def can_edit(self, user: User) -> bool:
"""Returns True if the user can edit the question"""
if user.is_superuser:
return True
if user in self.get_author_objects():
return True
return False
class SeriesImageBase(models.Model):
"""
+21
View File
@@ -1515,6 +1515,8 @@ class ExamViews(View, LoginRequiredMixin):
):
view_feedback = True
can_edit = question.can_edit(request.user)
return render(
request,
"{}/question_detail.html".format(self.app_name),
@@ -1526,6 +1528,7 @@ class ExamViews(View, LoginRequiredMixin):
"exam_length": exam_length,
"pos": pos,
"view_feedback": view_feedback,
"can_edit": can_edit,
},
)
@@ -3513,3 +3516,21 @@ class ExamGroupsUpdateBase(
kwargs = super(ExamGroupsUpdateBase, self).get_form_kwargs()
kwargs.update({"user": self.request.user})
return kwargs
class RedirectMixin():
def get_success_url(self) -> str:
if "redirect" in self.request.GET:
return self.request.GET["redirect"]
return super().get_success_url()
class UpdateQuestionMixin(RedirectMixin, RevisionMixin, UpdateView):
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs.update({"user": self.request.user})
return kwargs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["question"] = context["object"]
return context
+66 -57
View File
@@ -11,77 +11,86 @@
<div class="pre-whitespace multi-image-block"><b>Series:</b>
{% for series in question.series.all %}
<span class="series-block">
<span>
<span class="series-block-series-number">Series {{ forloop.counter }}:</span>
<a href="{% url 'longs:series_detail' pk=series.pk %}">
{{series.get_block}}
</a>
<span class="series-block">
<span>
<span class="series-block-series-number">Series {{ forloop.counter }}:</span>
<a href="{% url 'longs:series_detail' pk=series.pk %}">
{{series.get_block}}
</a>
<br>
<span class="series-block-popup-link">
<a href="#"
onclick="return window.create_popup_window('/longs/series/{{series.pk}}', 'Series')">Popup</a>
<br>
<span class="series-block-popup-link">
<a href="#"
onclick="return window.create_popup_window('/longs/series/{{series.pk}}', 'Series')">Popup</a>
</span>
</span>
</span>
</span>
{% endfor %}
<a href="{% url 'longs:long_series_id_create' pk=question.pk %}">Add new series</a><br />
</div>
<p><b>Author(s):</b> {% for author in question.author.all %} <a
href="{% url 'longs:author_detail' pk=author.pk %}">{{author}}</a>, {% endfor %}</p>
href="{% url 'longs:author_detail' pk=author.pk %}">{{author}}</a>, {% endfor %}</p>
<p><b>Checked by:</b> {% for verified in question.verified.all %} <a
href="{% url 'longs:verified_detail' pk=verified.pk %}">{{verified}}</a>, {% endfor %}</p>
href="{% url 'longs:verified_detail' pk=verified.pk %}">{{verified}}</a>, {% endfor %}</p>
{% comment %} <p><b>Scrapped:</b> {{ question.scrapped }} <a
href="{% url 'longs:long_scrap' pk=question.pk %}">(toggle)</a> {% endcomment %}
<div class="long-answer">
<p class="pre-whitespace"><b>Feedback:</b>
<div class="long-answer">
<p class="pre-whitespace"><b>Feedback:</b>
<pre>{{ question.feedback | safe}}</pre>
</p>
<details>
<summary>
<b>Model answers</b>
</summary>
{% if not question.model_differential_diagnosis and not question.model_interpretation and not question.model_management and not question.model_observations and not question.model_principle_diagnosis %}
<div class="alert alert-warning">No model answers.
{% if can_edit %}
<a href="{% url 'longs:long_update' pk=question.pk %}">Add some nowr.</a>
{% endif %}
</div>
{% endif %}
<p class="pre-whitespace"><b>Observations:</b>
<pre>{{ question.model_observations|default:"None" }}</pre>
</p>
<p class="pre-whitespace"><b>Interpretation:</b>
<pre>{{ question.model_interpretation|default:"None" }}</pre>
</p>
<p class="pre-whitespace"><b>Principle Diagnosis:</b>
<pre>{{ question.model_principle_diagnosis|default:"None" }}</pre>
</p>
<p class="pre-whitespace"><b>Differential Diagnosis:</b>
<pre>{{ question.model_differential_diagnosis|default:"None" }}</pre>
</p>
<p class="pre-whitespace"><b>Managment:</b>
<pre>{{ question.model_management|default:"None" }}</pre>
</p>
</details>
<p class="pre-whitespace">
<details>
<summary>
<b>Model answers</b>
</summary>
<p class="pre-whitespace"><b>Observations:</b>
<pre>{{ question.model_observations }}</pre>
</p>
<p class="pre-whitespace"><b>Interpretation:</b>
<pre>{{ question.model_interpretation }}</pre>
</p>
<p class="pre-whitespace"><b>Principle Diagnosis:</b>
<pre>{{ question.model_principle_diagnosis }}</pre>
</p>
<p class="pre-whitespace"><b>Differential Diagnosis:</b>
<pre>{{ question.model_differential_diagnosis }}</pre>
</p>
<p class="pre-whitespace"><b>Managment:</b>
<pre>{{ question.model_management }}</pre>
</p>
</details>
<p class="pre-whitespace">
<details>
<summary><b>Mark Scheme:</b></summary>
<summary><b>Mark Scheme:</b></summary>
<pre>{{ question.mark_scheme | safe}}</pre>
</details>
</p>
</div>
</p>
<div>
Exam(s): {% for exam in question.exams.all %}
</details>
</p>
</div>
</p>
<div>
Exam(s): {% for exam in question.exams.all %}
<a href="{% url 'longs:exam_overview' pk=exam.pk %}">{{ exam }}</a>,
{% endfor %}
</div>
<div>
{% include 'question_notes.html' %}
{% endfor %}
</div>
<div>
{% include 'question_notes.html' %}
</div>
<div>
JSON creation time: {{question.json_creation_time}} ({{question.json_creation_time|date:"c"}}),
JSON creation id: {{question.question_json_id}}
{% if question.recreate_json %}[JSON out of date]{% endif %}
</div>
<a href="{% url 'longs:question_json' pk=question.pk %}">JSON</a>
<a href="{% url 'longs:question_json_unbased' pk=question.pk %}">JSON (unbased)</a>
<a href="{% url 'longs:question_json_recreate' pk=question.pk %}">Refresh JSON cache</a>
</div>
<div>
JSON creation time: {{question.json_creation_time}} ({{question.json_creation_time|date:"c"}}),
JSON creation id: {{question.question_json_id}}
{% if question.recreate_json %}[JSON out of date]{% endif %}
</div>
<a href="{% url 'longs:question_json' pk=question.pk %}">JSON</a>
<a href="{% url 'longs:question_json_unbased' pk=question.pk %}">JSON (unbased)</a>
<a href="{% url 'longs:question_json_recreate' pk=question.pk %}">Refresh JSON cache</a>
+1 -1
View File
@@ -5,7 +5,7 @@
<div class="floating-header">
<a href="{% url 'longs:long_update' pk=question.pk %}" title="Edit the Long">Edit</a>
<a href="{% url 'longs:long_update' pk=question.pk %}?redirect={{request.path}}" title="Edit the Long">Edit</a>
<a href="{% url 'longs:long_clone' pk=question.pk %}" title="Clone the Long (duplicate everything but the images)">Clone</a>
<a href="{% url 'longs:long_delete' pk=question.pk %}" title="Delete the Rapid">Delete</a>
<a href="#" onclick="return window.create_popup_window('{% url 'feedback_create' question_type='long' pk=question.pk %}')"> Add Note</a>
+19 -13
View File
@@ -85,7 +85,9 @@ from generic.views import (
ExamGroupsUpdateBase,
ExamUpdateBase,
ExamViews,
RedirectMixin,
SeriesImagesZipViewBase,
UpdateQuestionMixin,
)
from reversion.views import RevisionMixin
import reversion
@@ -155,7 +157,10 @@ def question_detail(request, pk):
# raise PermissionDenied
# logging.debug(long.subspecialty.first().name.all())
return render(request, "longs/question_detail.html", {"question": long})
can_edit = long.can_edit(request.user)
return render(
request, "longs/question_detail.html", {"question": long, "can_edit": can_edit}
)
@login_required
@@ -500,7 +505,7 @@ class LongCreate(LongCreateBase):
class LongUpdate(
RevisionMixin, LoginRequiredMixin, AuthorOrCheckerRequiredMixin, UpdateView
UpdateQuestionMixin,AuthorOrCheckerRequiredMixin
):
model = Long
form_class = LongForm
@@ -510,13 +515,9 @@ class LongUpdate(
# #initial = {'date_of_death': '05/01/2018'}
# exclude = [ 'created_date', 'published_date' ]
def get_form_kwargs(self):
kwargs = super(LongUpdate, self).get_form_kwargs()
kwargs.update({"user": self.request.user})
return kwargs
def get_context_data(self, **kwargs):
context = super(LongUpdate, self).get_context_data(**kwargs)
context = super().get_context_data(**kwargs)
if self.request.POST:
context["series_formset"] = SeriesFormSet(
self.request.POST, self.request.FILES, instance=self.object
@@ -563,6 +564,7 @@ class LongUpdate(
return super().form_invalid(form)
class LongClone(LongCreateBase):
"""Clones a existing long"""
@@ -643,12 +645,12 @@ class LongSeriesView(LoginRequiredMixin, SingleTableMixin, FilterView):
filterset_class = LongSeriesFilter
#@user_is_long_marker
# @user_is_long_marker
def mark_answer_override(request, exam_id, question_number, cid):
return mark_answer(request, exam_id, question_number, cid, override=True)
#@user_is_long_marker
# @user_is_long_marker
@reversion.create_revision()
def mark_answer(request, exam_id, question_number, answer_id, override=False):
exam = get_object_or_404(Exam, pk=exam_id)
@@ -847,7 +849,7 @@ def mark_answer(request, exam_id, question_number, answer_id, override=False):
# @user_passes_test(user_is_admin, login_url="/accounts/login")
@login_required
#@user_is_long_marker
# @user_is_long_marker
def mark(request, exam_id, sk):
exam = get_object_or_404(Exam, pk=exam_id)
@@ -902,8 +904,6 @@ def mark(request, exam_id, sk):
)
@login_required
@user_is_author_or_long_series_checker
def long_series_order_dicom(request, pk):
@@ -985,14 +985,20 @@ class ExamAuthorUpdate(
form_class = ExamAuthorForm
template_name = "author_form.html"
class ExamMarkersUpdate(
RevisionMixin, CheckCanEditMixin, LoginRequiredMixin, AuthorRequiredMixin, UpdateView
RevisionMixin,
CheckCanEditMixin,
LoginRequiredMixin,
AuthorRequiredMixin,
UpdateView,
):
model = Exam
form_class = ExamMarkerForm
template_name = "markers_form.html"
class ExamGroupsUpdate(ExamGroupsUpdateBase):
model = Exam
form_class = ExamGroupsForm
+4 -5
View File
@@ -54,6 +54,7 @@ from generic.views import (
ExamUpdateBase,
ExamViews,
GenericViewBase,
UpdateQuestionMixin,
)
from reversion.views import RevisionMixin
@@ -374,7 +375,9 @@ class RapidAnswerUpdate(RevisionMixin, AuthorOrCheckerRequiredMixin, UpdateView)
return super().form_invalid(form)
class RapidUpdate(RevisionMixin, AuthorOrCheckerRequiredMixin, UpdateView):
class RapidUpdate(
UpdateQuestionMixin,AuthorOrCheckerRequiredMixin
):
model = Rapid
form_class = RapidForm
@@ -382,10 +385,6 @@ class RapidUpdate(RevisionMixin, AuthorOrCheckerRequiredMixin, UpdateView):
# #fields = [ 'condition' ]
# #initial = {'date_of_death': '05/01/2018'}
# exclude = [ 'created_date', 'published_date' ]
def get_form_kwargs(self):
kwargs = super(RapidUpdate, self).get_form_kwargs()
kwargs.update({"user": self.request.user})
return kwargs
def get_context_data(self, **kwargs):
context = super(RapidUpdate, self).get_context_data(**kwargs)
+2 -10
View File
@@ -50,6 +50,7 @@ from generic.views import (
ExamUpdateBase,
ExamViews,
GenericViewBase,
UpdateQuestionMixin,
exam_inactive,
)
@@ -317,19 +318,10 @@ class QuestionCreate(QuestionCreateBase):
return initial
class QuestionUpdate(RevisionMixin, AuthorOrCheckerRequiredMixin, UpdateView):
class QuestionUpdate(AuthorOrCheckerRequiredMixin, UpdateQuestionMixin):
model = Question
form_class = QuestionForm
def get_form_kwargs(self):
kwargs = super(QuestionUpdate, self).get_form_kwargs()
kwargs.update({"user": self.request.user})
return kwargs
def get_context_data(self, **kwargs):
context = super(QuestionUpdate, self).get_context_data(**kwargs)
return context
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.save()