.
This commit is contained in:
@@ -52,6 +52,9 @@ class AnatomyQuestionTable(tables.Table):
|
|||||||
# text='Clone',
|
# text='Clone',
|
||||||
# args=[A('pk')],
|
# args=[A('pk')],
|
||||||
# orderable=False)
|
# orderable=False)
|
||||||
|
delete = tables.LinkColumn(
|
||||||
|
"anatomy:question_delete", text="Delete", args=[A("pk")], orderable=False
|
||||||
|
)
|
||||||
exams = tables.ManyToManyColumn(verbose_name="Exams")
|
exams = tables.ManyToManyColumn(verbose_name="Exams")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
{% include 'confirm_delete.html' %}
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
<div class="question">
|
<div class="question">
|
||||||
<a href="{% url 'anatomy:anatomy_question_update' question.id %}" title="Edit the Question">Edit</a>
|
<a href="{% url 'anatomy:anatomy_question_update' question.id %}" title="Edit the Question">Edit</a>
|
||||||
<a href="{% url 'anatomy:question_clone' question.id %}" title="Clone the Question">Clone</a>
|
<a href="{% url 'anatomy:question_clone' question.id %}" title="Clone the Question">Clone</a>
|
||||||
|
<a href="{% url 'anatomy:question_delete' pk=question.pk %}" title="Delete the Question">Delete</a>
|
||||||
<a href="{% url 'admin:anatomy_anatomyquestion_change' question.id %}"
|
<a href="{% url 'admin:anatomy_anatomyquestion_change' question.id %}"
|
||||||
title="Edit the Question using the admin interface">Admin Edit</a>
|
title="Edit the Question using the admin interface">Admin Edit</a>
|
||||||
<div class="date">
|
<div class="date">
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ urlpatterns = [
|
|||||||
views.answer_question,
|
views.answer_question,
|
||||||
name="answer_question"),
|
name="answer_question"),
|
||||||
path("question/<int:pk>/clone", views.QuestionClone.as_view(), name="question_clone"),
|
path("question/<int:pk>/clone", views.QuestionClone.as_view(), name="question_clone"),
|
||||||
|
path("question/<int:pk>/delete", views.QuestionDelete.as_view(), name="question_delete"),
|
||||||
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
||||||
path("exam/<int:pk>/mark", views.AnatomyExamViews.mark_overview, name="mark_overview"),
|
path("exam/<int:pk>/mark", views.AnatomyExamViews.mark_overview, name="mark_overview"),
|
||||||
path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
|
path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from django import forms
|
|||||||
# from django.contrib.auth.models import User
|
# from django.contrib.auth.models import User
|
||||||
from django.contrib.auth.decorators import login_required, user_passes_test
|
from django.contrib.auth.decorators import login_required, user_passes_test
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.core.exceptions import PermissionDenied
|
||||||
|
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
|
||||||
@@ -64,6 +65,14 @@ from django.template.defaulttags import register
|
|||||||
|
|
||||||
from generic.mixins import SuperuserRequiredMixin
|
from generic.mixins import SuperuserRequiredMixin
|
||||||
|
|
||||||
|
class AuthorOrCheckerRequiredMixin(object):
|
||||||
|
def get_object(self, *args, **kwargs):
|
||||||
|
obj = super().get_object(*args, **kwargs)
|
||||||
|
if self.request.user.groups.filter(name="anatomy_checker").exists():
|
||||||
|
return obj
|
||||||
|
if self.request.user not in obj.author.all():
|
||||||
|
raise PermissionDenied() # or Http404
|
||||||
|
return obj
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def get_item(dictionary, key):
|
def get_item(dictionary, key):
|
||||||
@@ -949,3 +958,6 @@ AnatomyExamViews = ExamViews(Exam, "anatomy", "anatomy", loadJsonAnswer)
|
|||||||
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
|
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
|
||||||
model = CidUserAnswer
|
model = CidUserAnswer
|
||||||
success_url = reverse_lazy("anatomy:anatomy_user_answer_view")
|
success_url = reverse_lazy("anatomy:anatomy_user_answer_view")
|
||||||
|
class QuestionDelete(AuthorOrCheckerRequiredMixin, DeleteView):
|
||||||
|
model = AnatomyQuestion
|
||||||
|
success_url = reverse_lazy("anatomy:anatomy_question_view")
|
||||||
@@ -57,6 +57,9 @@ class LongTable(tables.Table):
|
|||||||
clone = tables.LinkColumn(
|
clone = tables.LinkColumn(
|
||||||
"longs:long_clone", text="Clone", args=[A("pk")], orderable=False
|
"longs:long_clone", text="Clone", args=[A("pk")], orderable=False
|
||||||
)
|
)
|
||||||
|
delete = tables.LinkColumn(
|
||||||
|
"longs:long_delete", text="Delete", args=[A("pk")], orderable=False
|
||||||
|
)
|
||||||
series = LongImageColumn("Images", orderable=False)
|
series = LongImageColumn("Images", orderable=False)
|
||||||
|
|
||||||
#series = tables.ManyToManyColumn(verbose_name="Exams")
|
#series = tables.ManyToManyColumn(verbose_name="Exams")
|
||||||
@@ -93,6 +96,10 @@ class LongSeriesTable(tables.Table):
|
|||||||
|
|
||||||
images = LongSeriesImageColumn("Images", orderable=False)
|
images = LongSeriesImageColumn("Images", orderable=False)
|
||||||
|
|
||||||
|
delete = tables.LinkColumn(
|
||||||
|
"longs:long_series_delete", text="Delete", args=[A("pk")], orderable=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = LongSeries
|
model = LongSeries
|
||||||
template_name = "django_tables2/bootstrap4.html"
|
template_name = "django_tables2/bootstrap4.html"
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
{% include 'confirm_delete.html' %}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{% include 'confirm_delete.html' %}
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
<a href="{% url 'longs:long_update' pk=question.pk %}" title="Edit the Long">Edit</a>
|
<a href="{% url 'longs:long_update' pk=question.pk %}" 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_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="{% url 'longs:long_add_note' pk=question.pk %}"> Add Note</a>
|
<a href="{% url 'longs:long_add_note' pk=question.pk %}"> Add Note</a>
|
||||||
{% if request.user.is_superuser %}
|
{% if request.user.is_superuser %}
|
||||||
<a href="{% url 'admin:longs_long_change' question.id %}" title="Edit the Long using the admin interface">Admin Edit</a>
|
<a href="{% url 'admin:longs_long_change' question.id %}" title="Edit the Long using the admin interface">Admin Edit</a>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ urlpatterns = [
|
|||||||
path("question/", views.LongView.as_view(), name="long_view"),
|
path("question/", views.LongView.as_view(), name="long_view"),
|
||||||
path("series/", views.LongSeriesView.as_view(), name="long_series_view"),
|
path("series/", views.LongSeriesView.as_view(), name="long_series_view"),
|
||||||
path("series/<int:pk>", views.long_series_detail, name="long_series_detail"),
|
path("series/<int:pk>", views.long_series_detail, name="long_series_detail"),
|
||||||
|
path("series/<int:pk>/delete", views.LongSeriesDelete.as_view(), name="long_series_delete"),
|
||||||
# path("unchecked/", views.unchecked_list, name="unchecked_list"),
|
# path("unchecked/", views.unchecked_list, name="unchecked_list"),
|
||||||
# path("verified/<int:pk>/", views.verified_detail, name="verified_detail"),
|
# path("verified/<int:pk>/", views.verified_detail, name="verified_detail"),
|
||||||
path("question/<int:pk>/", views.long_detail, name="long_detail"),
|
path("question/<int:pk>/", views.long_detail, name="long_detail"),
|
||||||
@@ -19,6 +20,7 @@ urlpatterns = [
|
|||||||
# path("verified/", views.verified, name="verified"),
|
# path("verified/", views.verified, name="verified"),
|
||||||
# path("all_questions/", views.all_questions, name="all_questions"),
|
# path("all_questions/", views.all_questions, name="all_questions"),
|
||||||
path("question/<int:pk>/scrap", views.long_scrap, name="long_scrap"),
|
path("question/<int:pk>/scrap", views.long_scrap, name="long_scrap"),
|
||||||
|
path("question/<int:pk>/delete", views.LongDelete.as_view(), name="long_delete"),
|
||||||
path("exam/<int:pk>/<int:sk>/<int:tk>/mark", views.mark_answer, name="mark_answer"),
|
path("exam/<int:pk>/<int:sk>/<int:tk>/mark", views.mark_answer, name="mark_answer"),
|
||||||
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
||||||
path("exam/<int:pk>/mark", views.LongExamViews.mark_overview, name="mark_overview"),
|
path("exam/<int:pk>/mark", views.LongExamViews.mark_overview, name="mark_overview"),
|
||||||
|
|||||||
+13
-2
@@ -63,7 +63,7 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class AuthorOrCheckerRequiredMixin(object):
|
class AuthorOrCheckerRequiredMixin(object):
|
||||||
def get_object(self, *args, **kwargs):
|
def get_object(self, *args, **kwargs):
|
||||||
obj = super(UpdateView, self).get_object(*args, **kwargs)
|
obj = super().get_object(*args, **kwargs)
|
||||||
if self.request.user.groups.filter(name="long_checker").exists() or self.request.user.is_superuser:
|
if self.request.user.groups.filter(name="long_checker").exists() or self.request.user.is_superuser:
|
||||||
return obj
|
return obj
|
||||||
if self.request.user not in obj.get_author_objects():
|
if self.request.user not in obj.get_author_objects():
|
||||||
@@ -71,7 +71,6 @@ class AuthorOrCheckerRequiredMixin(object):
|
|||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# def index(request):
|
# def index(request):
|
||||||
# other_longs = Long.objects.exclude(author=request.user.pk)
|
# other_longs = Long.objects.exclude(author=request.user.pk)
|
||||||
# user_longs = Long.objects.filter(author=request.user.pk)
|
# user_longs = Long.objects.filter(author=request.user.pk)
|
||||||
@@ -228,6 +227,18 @@ class AddNote(LoginRequiredMixin, CreateView):
|
|||||||
|
|
||||||
# form.instance.author.add(self.request.user.id)
|
# form.instance.author.add(self.request.user.id)
|
||||||
|
|
||||||
|
#@login_required
|
||||||
|
#@user_is_author_or_long_checker
|
||||||
|
#def long_delete(request, pk):
|
||||||
|
#q = get_object_or_404(Long, pk=pk)
|
||||||
|
#q.delete()
|
||||||
|
class LongDelete(AuthorOrCheckerRequiredMixin, DeleteView):
|
||||||
|
model = Long
|
||||||
|
success_url = reverse_lazy("longs:long_view")
|
||||||
|
|
||||||
|
class LongSeriesDelete(AuthorOrCheckerRequiredMixin, DeleteView):
|
||||||
|
model = LongSeries
|
||||||
|
success_url = reverse_lazy("longs:long_series_view")
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def long_clone(request, pk):
|
def long_clone(request, pk):
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ class RapidTable(tables.Table):
|
|||||||
text='Clone',
|
text='Clone',
|
||||||
args=[A('pk')],
|
args=[A('pk')],
|
||||||
orderable=False)
|
orderable=False)
|
||||||
|
delete = tables.LinkColumn('rapids:question_delete',
|
||||||
|
text='Delete',
|
||||||
|
args=[A('pk')],
|
||||||
|
orderable=False)
|
||||||
images = ImageColumn("images", orderable=False)
|
images = ImageColumn("images", orderable=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
<a href="{% url 'rapids:rapid_update' pk=question.pk %}" title="Edit the Rapid">Edit</a>
|
<a href="{% url 'rapids:rapid_update' pk=question.pk %}" title="Edit the Rapid">Edit</a>
|
||||||
<a href="{% url 'rapids:rapid_clone' pk=question.pk %}" title="Clone the Rapid (duplicate everything but the images)">Clone</a>
|
<a href="{% url 'rapids:rapid_clone' pk=question.pk %}" title="Clone the Rapid (duplicate everything but the images)">Clone</a>
|
||||||
|
<a href="{% url 'rapids:question_delete' pk=question.pk %}" title="Delete the Rapid">Delete</a>
|
||||||
<a href="{% url 'rapids:rapid_add_note' pk=question.pk %}"> Add Note</a>
|
<a href="{% url 'rapids:rapid_add_note' pk=question.pk %}"> Add Note</a>
|
||||||
{% if request.user.is_superuser %}
|
{% if request.user.is_superuser %}
|
||||||
<a href="{% url 'admin:rapids_rapid_change' question.id %}" title="Edit the Rapid using the admin interface">Admin Edit</a>
|
<a href="{% url 'admin:rapids_rapid_change' question.id %}" title="Edit the Rapid using the admin interface">Admin Edit</a>
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
{% include 'confirm_delete.html' %}
|
||||||
@@ -17,6 +17,7 @@ urlpatterns = [
|
|||||||
#path("verified/", views.verified, name="verified"),
|
#path("verified/", views.verified, name="verified"),
|
||||||
#path("all_questions/", views.all_questions, name="all_questions"),
|
#path("all_questions/", views.all_questions, name="all_questions"),
|
||||||
path("question/<int:pk>/scrap", views.rapid_scrap, name="rapid_scrap"),
|
path("question/<int:pk>/scrap", views.rapid_scrap, name="rapid_scrap"),
|
||||||
|
path("question/<int:pk>/delete", views.QuestionDelete.as_view(), name="question_delete"),
|
||||||
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
||||||
path("exam/<int:pk>/mark", views.RapidExamViews.mark_overview, name="mark_overview"),
|
path("exam/<int:pk>/mark", views.RapidExamViews.mark_overview, name="mark_overview"),
|
||||||
# path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
|
# path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
|
||||||
|
|||||||
+4
-1
@@ -70,7 +70,7 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class AuthorOrCheckerRequiredMixin(object):
|
class AuthorOrCheckerRequiredMixin(object):
|
||||||
def get_object(self, *args, **kwargs):
|
def get_object(self, *args, **kwargs):
|
||||||
obj = super(UpdateView, self).get_object(*args, **kwargs)
|
obj = super().get_object(*args, **kwargs)
|
||||||
if self.request.user.groups.filter(name="rapid_checker").exists():
|
if self.request.user.groups.filter(name="rapid_checker").exists():
|
||||||
return obj
|
return obj
|
||||||
if self.request.user not in obj.author.all():
|
if self.request.user not in obj.author.all():
|
||||||
@@ -871,5 +871,8 @@ def exam_scores_cid_user(request, pk, sk):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class QuestionDelete(AuthorOrCheckerRequiredMixin, DeleteView):
|
||||||
|
model = Rapid
|
||||||
|
success_url = reverse_lazy("rapids:rapid_view")
|
||||||
|
|
||||||
RapidExamViews = ExamViews(Exam, "rapids", "rapid", loadJsonAnswer)
|
RapidExamViews = ExamViews(Exam, "rapids", "rapid", loadJsonAnswer)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h2>Deleting stuff</h2>
|
||||||
|
|
||||||
|
<form method="post">{% csrf_token %}
|
||||||
|
<p>Are you sure you want to delete "{{ object }}"?</p>
|
||||||
|
<input type="submit" value="Confirm">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock content %}
|
||||||
Reference in New Issue
Block a user