from django.contrib import admin
from django.core.exceptions import ValidationError
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from nested_admin import nested
from nested_admin.formsets import NestedInlineFormSet
import oioioi.contests.admin
from oioioi.base.admin import NO_CATEGORY
from oioioi.contests.current_contest import reverse
from oioioi.quizzes.models import (
Quiz,
QuizAnswer,
QuizAnswerPicture,
QuizQuestion,
QuizQuestionPicture,
)
# If there was a need to get rid of nested_admin, you can create dummy inlines,
# that add links to ModelAdmin with nested inlines on another page,
# see how QuizInline works.
[docs]class QuizPictureInline(nested.NestedStackedInline):
[docs] def has_add_permission(self, request, obj=None):
return True
[docs] def has_change_permission(self, request, obj=None):
return True
[docs] def has_delete_permission(self, request, obj=None):
return True
[docs] def has_view_permission(self, request, obj=None):
return self.has_change_permission(request, obj)
[docs]class QuizQuestionPictureInline(QuizPictureInline):
[docs] model = QuizQuestionPicture
[docs]class QuizAnswerPictureInline(QuizPictureInline):
[docs] model = QuizAnswerPicture
[docs]class QuizAnswerInline(nested.NestedTabularInline):
[docs] sortable_field_name = 'order'
[docs] inlines = (QuizAnswerPictureInline,)
[docs] def has_add_permission(self, request, obj=None):
return True
[docs] def has_change_permission(self, request, obj=None):
return True
[docs] def has_delete_permission(self, request, obj=None):
return True
[docs]class QuizQuestionInline(nested.NestedStackedInline):
[docs] sortable_field_name = 'order'
[docs] inlines = (QuizAnswerInline, QuizQuestionPictureInline,)
[docs] def has_add_permission(self, request, obj=None):
return True
[docs] def has_change_permission(self, request, obj=None):
return True
[docs] def has_delete_permission(self, request, obj=None):
return True
[docs] def has_view_permission(self, request, obj=None):
return self.has_change_permission(request, obj)
[docs]class QuizModelAdmin(nested.NestedModelAdmin):
[docs] inlines = (QuizQuestionInline,)
def __init__(self, parent_model, admin_site):
super(QuizModelAdmin, self).__init__(parent_model, admin_site)
self.exclude = [f.name for f in Quiz._meta.get_fields()]
[docs] def has_delete_permission(self, request, obj=None):
return False
[docs] def has_change_permission(self, request, obj=None):
if obj is None:
return request.user.is_superuser
# because Quiz questions are bound to the Quiz and not QuizInstance,
# only the owner (author) can edit them
# otherwise someone could add the Quiz to contest to get edit
# perimssion and their changes would propagate to all other instances
return obj.author == request.user or request.user.is_superuser
[docs] def has_view_permission(self, request, obj=None):
return self.has_change_permission(request, obj)
# This is required to be able to generate a link to editing quiz questions
oioioi.contests.admin.contest_site.register(Quiz, QuizModelAdmin)
[docs]class QuizInline(admin.StackedInline):
[docs] fields = [] # < this doesn't exclude the fields
[docs] readonly_fields = ['edit']
[docs] def has_delete_permission(self, request, obj=None):
return False
[docs] def has_change_permission(self, request, obj=None):
return True
[docs] def has_view_permission(self, request, obj=None):
return self.has_change_permission(request, obj)
[docs] def edit(self, instance):
url = reverse('oioioiadmin:quizzes_quiz_change', args=[instance.pk])
return mark_safe(
u'<a href="{url}">{text}</a>'.format(url=url, text=_("Edit quiz questions"))
)
def __init__(self, parent_model, admin_site):
super(QuizInline, self).__init__(parent_model, admin_site)
self.exclude = [f.name for f in Quiz._meta.get_fields()]
[docs]class QuizAdminMixin(object):
"""Adds :class:`~oioioi.quizzes.models.Quiz` to an admin panel."""
def __init__(self, *args, **kwargs):
super(QuizAdminMixin, self).__init__(*args, **kwargs)
self.inlines = tuple(self.inlines) + (QuizInline,)