Source code for devilry.apps.gradeeditors.models

from django.db.models.signals import post_save
from django.core.exceptions import ValidationError
from django.db import models
from django.contrib.auth.models import User

from devilry.apps.core.models import Delivery, Assignment, StaticFeedback
from registry import gradeeditor_registry


[docs]class Config(models.Model): """ Stored by admins. .. attribute:: gradeeditorid A ``gradeeditorid`` that is used to get the :class:`devilry.apps.gradeeditors.registry.RegistryItem` for this config. .. attribute:: assignment The primary key. This means we have one config for each assignment. .. attribute:: config A text field where the config editor can store its data in any format it chooses. JSON is usually a good choice because of easy interraction with JavaScript. """ gradeeditorid = models.SlugField() assignment = models.OneToOneField(Assignment, related_name='gradeeditor_config', primary_key=True) config = models.TextField(null=True, blank=True) def _get_gradeeditor(self): return gradeeditor_registry[self.gradeeditorid]
[docs] def clean(self): """ Gets a :class:`devilry.apps.gradeeditors.registry.RegistryItem` from the ``gradeeditor_registry`` in :mod:`devilry.apps.gradeeditor.registry`. Uses :meth:`devilry.apps.gradeeditors.registry.RegistryItem.validate_config` to validate the config before saving it. """ try: config = self._get_gradeeditor() except KeyError, e: raise ValidationError('Invalid grade editor: {0}'.format(self.gradeeditorid)) if self.config: config.validate_config(self.config)
[docs]def create_gradeconfig_for_assignment(sender, **kwargs): """ Signal handler which is invoked when an Assignment is created. Create default grade Config for Assignment with ``config=''`` if the assignment has no grade Config. :param kwargs: Must have an *instance* key with an assignment object as value. """ assignment = kwargs['instance'] try: config = assignment.gradeeditor_config except Config.DoesNotExist: config = Config(assignment=assignment, gradeeditorid=gradeeditor_registry.getdefaultkey(), config='') config.save()
post_save.connect(create_gradeconfig_for_assignment, sender=Assignment)
[docs]class FeedbackDraft(models.Model): """ Stored by examiners. """ delivery = models.ForeignKey(Delivery) draft = models.TextField() save_timestamp = models.DateTimeField(auto_now=True, blank=False, null=False, help_text='Time when this feedback was saved. Since FeedbackDraft ' 'is immutable, this never changes.') saved_by = models.ForeignKey(User) published = models.BooleanField(default=False, help_text='Has this draft been published as a StaticFeedback? Setting this to true on create automatically creates a StaticFeedback.') staticfeedback = models.OneToOneField(StaticFeedback, blank=True, null=True, related_name='gradeeditor_feedbackdraft', help_text='The StaticFeedback where this was published if this draft has been published.') def _get_config(self): return self.delivery.deadline.assignment_group.parentnode.gradeeditor_config def clean(self): if self.id == None: # If creating a new FeedbackDraft try: config = self._get_config() except Config.DoesNotExist: raise ValidationError(('Can not create feedback on delivery:{0} ' 'because its assignment does not have a ' 'gradeeditor_config.').format(self.delivery)) else: gradeeditor = config._get_gradeeditor() gradeeditor.validate_draft(self.draft, config.config) if not self.published: self.staticfeedback = None # We should NEVER set staticfeedback if published is not True else: raise ValidationError('FeedbackDraft is immutable (it can not be changed).')
[docs] def save(self, *args, **kwargs): """ Save the draft and optionally a :class:`devilry.core.models.StaticFeedback` in the database. The ``StaticFeedback`` is only saved if ``self.publish`` is ``True``. Uses :meth:`to_staticfeedback` to create the staticfeedback. """ if self.published: _tmp_staticfeedback = self.to_staticfeedback() _tmp_staticfeedback.full_clean() _tmp_staticfeedback.save() self.staticfeedback = _tmp_staticfeedback # Note: We use _tmp_staticfeedback because if we need a variable in which to store the staticfeedback while we save it. We can not just save self.staticfeedback() because that would just create create a copy without actually setting self.staticfeedback to the newly saved value. super(FeedbackDraft, self).save(*args, **kwargs)
[docs] def to_staticfeedback(self): """ Return a staticfeedback generated from self. """ config = self._get_config() gradeeditor = config._get_gradeeditor() kwargs = gradeeditor.draft_to_staticfeedback_kwargs(self.draft, config.config) # Create StaticFeedback from kwargs. We copy by key instead of **kwargs to make sure we dont get anything extra. return StaticFeedback(is_passing_grade=kwargs['is_passing_grade'], grade=kwargs['grade'], points=kwargs['points'], rendered_view=kwargs['rendered_view'], delivery=self.delivery, save_timestamp=None, saved_by=self.saved_by)