Source code for oioioi.quizzes.admin

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 QuizAnswerFormset(NestedInlineFormSet):
[docs] def clean(self): super(QuizAnswerFormset, self).clean() is_empty = True for form in self.forms: if form.cleaned_data and not form.cleaned_data.get('DELETE'): is_empty = False if is_empty: raise ValidationError(_("A question needs at least one answer."))
[docs]class QuizPictureInline(nested.NestedStackedInline):
[docs] extra = 0
[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] model = QuizAnswer
[docs] formset = QuizAnswerFormset
[docs] sortable_field_name = 'order'
[docs] extra = 0
[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] model = QuizQuestion
[docs] sortable_field_name = 'order'
[docs] extra = 0
[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] model = Quiz
[docs] inlines = (QuizQuestionInline,)
[docs] class Media(object):
[docs] css = {'all': ('quizzes/quizadmin.css',)}
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] model = Quiz
[docs] fields = [] # < this doesn't exclude the fields
[docs] readonly_fields = ['edit']
[docs] category = NO_CATEGORY
[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,)