super(ScoreForm, self).__init__(*args, **kwargs)
self.fields['file'].required = False
self.fields['score'].required = True
+
+class MassScoreForm(ScoreForm):
+ def __init__(self, *args, **kwargs):
+ super(MassScoreForm, self).__init__(*args, **kwargs)
+ self.table_errors = {}
+ self.fields['score'].required = False
+
+ def clean(self):
+ cleaned_data = super(MassScoreForm, self).clean()
+
+ errors = {}
+ valid = []
+
+ for key in self.data.keys():
+ if key.startswith('student'):
+ student = self.data[key]
+ if student:
+ score = self.data[key.replace('student', 'score')]
+ try:
+ score = int(score)
+ except ValueError:
+ errors[key] = u"Note invalide"
+ continue
+ valid.append((student, score))
+
+ cleaned_data['scores'] = valid
+ self.table_errors = errors
+
+ if errors:
+ raise forms.ValidationError("Certaines notes sont invalides")
+ return cleaned_data
--- /dev/null
+{% extends "exam/scores.html" %}
+{% load telemeta_utils %}
+{% load teleforma_tags %}
+{% load i18n %}
+{% load thumbnail %}
+
+{% block extra_javascript %}
+{% if upload %}
+ <script>
+ $(document).ready(function(){
+ $('#loading').hide();
+ });
+
+ $(function() {
+ $('#submit_button').unbind('click').click(function() {
+ $(window).unbind('beforeunload');
+ // b2.unbind('click');
+ $('#id_status').val("5");
+ $('#id_period').val("{{ period.id }}");
+ $(this).hide();
+ $('#loading').show();
+ $('#_ScriptForm').submit();
+ });
+ });
+ </script>
+{% endif %}
+{% endblock extra_javascript %}
+
+{% block answers %}
+
+<div class="course_title">
+ Saisie en masse de notes
+</div>
+<br />
+
+{% if messages %}
+ <div class="messages">
+ {% for message in messages %}
+ <div{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</div>
+ {% endfor %}
+ </div>
+{% endif %}
+
+<div class="course_content" id="media_infos" style="font-size: 115%;">
+ <form method="post" id="_ScriptForm" action="" enctype="multipart/form-data" data-ajax="false">{% csrf_token %}
+ <table>
+ <br />
+ <tr><td colspan="2">{% for error in form.non_field_errors %}<li class="error">{{ error }}</li>{% endfor %}</td></tr>
+ {% for field in form %}
+ <tr>
+ {% if not field.html_name in create_fields %}
+ <td>{{ field.label_tag.as_hidden }}</td><td>{{ field.as_hidden }}</td>
+ {% else %}
+ <td>
+ {{ field.label_tag }}:
+ </td>
+ <td>
+ {{ field }}
+ </td>
+ <td>
+ {% for error in field.errors %}
+ <div class="error">
+ {{ error|escape }}
+ </div>
+ {% endfor %}
+ </td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </table>
+
+ <table>
+ <thead>
+ <tr>
+ <th>Étudiant</th>
+ <th>Note</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for row in rows %}
+ <tr>
+ <td>
+ <input name="{{ row.student_name }}" value="{{ row.student_value }}" />
+ </td>
+ <td>
+ <input name="{{ row.score_name }}" value="{{ row.score_value }}" />
+ </td>
+ {% if row.error %}
+ <td>
+ <div class="error">
+ {{ row.error }}
+ </div>
+ </td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </form>
+ {% if upload %}
+ <br />
+ <center>
+ <a href="#" id="submit_button" class="component_icon button icon_next">{% trans "Submit" %}</a>
+ <img id="loading" src="/static/teleforma/images/loading.gif" style="vertical-align:middle" alt="loading" />
+ </center>
+ {% endif %}
+ <br /><br />
+
+</div>
+</div>
+
+{% endblock answers %}
from django.utils.translation import ugettext_lazy as _
import json
import numpy as np
+from django.contrib.auth.decorators import permission_required
STUDENT = 0
CORRECTOR = 1
else:
context['upload'] = False
+ context['admin'] = self.request.user.is_superuser
+
return context
class ScriptsListMixinView(ScriptMixinView):
return super(ScriptCreateView, self).form_valid(form)
def form_invalid(self, form):
- messages.info(self.request, _("There was a problem with your submission. Please try again, later if possible."))
+ messages.error(self.request, _("There was a problem with your submission. Please try again, later if possible."))
return super(ScriptCreateView, self).form_invalid(form)
def get_context_data(self, **kwargs):
template_name='exam/score_form.html'
form_class = ScoreForm
+ def form_invalid(self, form):
+ messages.error(self.request, "Il y une erreur sur ce formulaire, veuillez le corriger.")
+ return super(ScriptCreateView, self).form_invalid(form)
+
def get_success_url(self):
period = Period.objects.get(id=self.kwargs['period_id'])
return reverse_lazy('teleforma-exam-scripts-scores-all', kwargs={'period_id':period.id})
correctors.append({'label': '%s %s' % (corrector.last_name, corrector.first_name), 'value':corrector.id})
dump = json.dumps(correctors)
return HttpResponse(dump, content_type='application/json')
+
+class MassScoreCreateView(ScoreCreateView):
+
+ template_name='exam/mass_score_form.html'
+ form_class = MassScoreForm
+
+ def get_allowed_students(self, course_id, session):
+ """
+ Get allowed students for given course and session
+ """
+ students = Student.objects.filter(period = self.period)
+
+ # Exclude students who already have a script for this session
+ scripts = Script.objects.filter(period = self.period,
+ session = session,
+ course_id = course_id).values('author_id')
+ scripts = set([s['author_id'] for s in scripts])
+
+ students = students.exclude(user_id__in = scripts)
+
+ res = []
+ for student in students:
+ user = student.user
+ # FIXME : Filter those who access the course, but that's very slow,
+ # so I disable it for now - we'll see if we can do that faster later
+ # courses = get_courses(user)
+ # if course_id in [ c['course'].id for c in courses ]:
+ res.append({ 'id': user.id,
+ 'name': str(user) })
+
+ return res
+
+ def form_valid(self, form):
+ course = form.cleaned_data['course']
+ session = form.cleaned_data['session']
+ sc_type = form.cleaned_data['type']
+
+ allowed_students = self.get_allowed_students(course.id,
+ session)
+ allowed_students = set([ str(s['id']) for s in allowed_students ])
+ done = set()
+ nb_errors = 0
+ nb_ok = 0
+
+ for student, score in form.cleaned_data['scores']:
+ if student in done:
+ nb_errors += 1
+ continue
+ if not student in allowed_students:
+ nb_errors += 1
+ continue
+ nb_ok += 1
+ done.add(student)
+ obj = Script(course = course,
+ period = self.period,
+ session = session,
+ author_id = student,
+ type = sc_type,
+ score = score,
+ status = 7)
+ obj.save()
+
+ messages.info(self.request, "%d notes créées, %d en erreur (copie déjà existante, ...)" % (nb_ok, nb_errors))
+
+ return redirect(self.get_success_url())
+
+ def get_context_data(self, **kwargs):
+ context = super(MassScoreCreateView, self).get_context_data(**kwargs)
+ context['create_fields'] = ['course', 'session', 'type' ]
+ context['rows'] = [ { 'student_name': 'student%d' % i,
+ 'score_name': 'score%d' % i } for i in range(20) ]
+ for row in context['rows']:
+ row['student_value'] = self.request.POST.get(row['student_name'], '')
+ row['score_value'] = self.request.POST.get(row['score_name'], '')
+ row['error'] = context['form'].table_errors.get(row['student_name'], None)
+ return context
+
+ @method_decorator(permission_required('is_superuser'))
+ def dispatch(self, *args, **kwargs):
+ return super(ScoreCreateView, self).dispatch(*args, **kwargs)