1 # -*- coding: utf-8 -*-
5 from django.contrib import admin
6 from django import forms
7 from django.utils import simplejson
8 from django.utils.safestring import mark_safe
9 from django.core.urlresolvers import reverse
10 from django.conf.urls import url, patterns
11 from django.shortcuts import render
12 from django.contrib.auth.models import User
13 from .models import Submission, Assignment, Attachment, exercises
14 from .middleware import get_current_request
17 def get_user_exercises(user):
19 assignment = Assignment.objects.get(user = user)
20 return [e for e in exercises if e['id'] in assignment.exercises]
21 except Assignment.DoesNotExist:
25 readonly_fields = ('submitted_by', 'first_name', 'last_name', 'email', 'key', 'key_sent')
27 class AttachmentWidget(forms.Widget):
28 def render(self, name, value, *args, **kwargs):
30 a_tag = '<a href="%s">%s</a>' % (value, value)
33 return mark_safe(('<input type="hidden" name="%s" value="%s"/>' + a_tag) % (name, value))
35 class SubmissionFormBase(forms.ModelForm):
38 exclude = ('answers', 'marks', 'contact') + readonly_fields
41 def get_open_answer(answers, exercise):
42 def get_option(options, id):
43 for option in options:
44 if option['id'] == int(id):
47 exercise_id = str(exercise['id'])
48 answer = answers[exercise_id]
49 if exercise['type'] == 'open':
50 if isinstance(answer, list):
53 field = get_option(exercise['fields'], part['id'])
54 toret += '- %s:\n\n%s\n\n' % (field['caption'], part['text'])
57 if exercise['type'] == 'edumed_wybor':
58 ok = set(map(str, exercise['answer'])) == set(map(str,answer['closed_part']))
59 toret = u'Czesc testowa [%s]:\n' % ('poprawna' if ok else 'niepoprawna')
60 for selected in answer['closed_part']:
61 option = get_option(exercise['options'], selected)
62 toret += '%s: %s\n' % (selected, option['text'])
64 toret += u'<nie wybrano odpowiedzi>\n'
65 toret += u'\nCzesc otwarta (%s):\n\n' % ' '.join(exercise['open_part'])
66 toret += answer['open_part']
71 def get_form(request, submission):
73 if submission.answers:
74 answers = simplejson.loads(submission.answers)
75 user_exercises = get_user_exercises(request.user)
76 for exercise in exercises:
77 if exercise not in user_exercises:
80 answer_field_name = 'exercise_%s' % exercise['id']
81 mark_field_name = 'markof_%s_by_%s' % (exercise['id'], request.user.id)
82 if exercise['type'] in ('open', 'file_upload') or exercise.get('open_part', None):
83 if exercise['type'] == 'file_upload':
85 attachment = Attachment.objects.get(submission = submission, exercise_id = exercise['id'])
86 except Attachment.DoesNotExist:
88 widget = AttachmentWidget
89 initial = attachment.file.url if attachment else None
91 widget = forms.Textarea(attrs={'readonly':True})
92 initial = get_open_answer(answers, exercise)
94 fields[answer_field_name] = forms.CharField(
97 label = 'Rozwiązanie zadania %s' % exercise['id']
100 fields[mark_field_name] = forms.ChoiceField(
101 choices = [(None, '-')] + [(i,i) for i in range(exercise['max_points']+1)],
102 initial = submission.get_mark(user_id = request.user.id, exercise_id = exercise['id']),
103 label = u'Twoja ocena zadania %s' % exercise['id']
106 if not request.user.is_superuser:
107 class Meta(SubmissionFormBase.Meta):
109 Meta.exclude += ('examiners',)
110 fields['Meta'] = Meta
112 return type('SubmissionForm', (SubmissionFormBase,), fields)
115 class SubmissionAdmin(admin.ModelAdmin):
116 list_display = ('__unicode__', 'todo', 'examiners_repr')
117 readonly_fields = readonly_fields
119 def get_form(self, request, obj, **kwargs):
120 return get_form(request, obj)
122 def submitted_by(self, instance):
124 return '<a href="%s">%s</a>' % (
125 reverse('admin:contact_contact_change', args = [instance.contact.id]),
126 instance.contact.contact
129 submitted_by.allow_tags = True
130 submitted_by.short_description = "Zgłoszony/a przez"
132 def todo(self, submission):
133 user = get_current_request().user
134 user_exercises = get_user_exercises(user)
135 user_marks = submission.marks.get(str(user.id), {})
136 return ','.join([str(e['id']) for e in user_exercises if str(e['id']) not in user_marks.keys()])
137 todo.short_description = 'Twoje nieocenione zadania'
139 def examiners_repr(self, submission):
140 return ', '.join([u.username for u in submission.examiners.all()])
141 examiners_repr.short_description = 'Przypisani do zgłoszenia'
143 def save_model(self, request, submission, form, change):
144 for name, value in form.cleaned_data.items():
145 if name.startswith('markof_'):
146 parts = name.split('_')
147 exercise_id = parts[1]
149 submission.set_mark(user_id = user_id, exercise_id = exercise_id, mark = value)
152 def changelist_view(self, request, extra_context=None):
153 context = dict(examiners = [])
154 assignments = Assignment.objects.all()
155 if not request.user.is_superuser:
156 assignments = assignments.filter(user = request.user)
157 for assignment in assignments:
158 examiner = dict(name = assignment.user.username, todo = 0)
159 for submission in Submission.objects.filter(examiners = assignment.user):
160 for exercise_id in assignment.exercises:
161 if submission.get_mark(user_id = assignment.user.id, exercise_id = exercise_id) is None:
162 examiner['todo'] += 1
163 context['examiners'].append(examiner)
164 return super(SubmissionAdmin, self).changelist_view(request, extra_context = context)
166 def queryset(self, request):
167 qs = super(SubmissionAdmin, self).queryset(request)
168 if not request.user.is_superuser:
169 qs = qs.filter(examiners = request.user)
173 urls = super(SubmissionAdmin, self).get_urls()
175 url(r'^report/$', self.admin_site.admin_view(report_view), name='wtem_admin_report')
176 ) + super(SubmissionAdmin, self).get_urls()
179 class SubmissionsSet:
180 def __init__(self, submissions):
181 self.submissions = submissions
182 self.examiners_by_exercise = dict()
183 for submission in submissions:
184 for user_id, marks in submission.marks.items():
185 user = User.objects.get(pk=user_id)
186 for exercise_id in marks.keys():
187 examiners = self.examiners_by_exercise.setdefault(exercise_id, [])
188 if not user in examiners:
189 examiners.append(user)
191 def report_view(request):
192 submissions = Submission.objects.all()
193 submissions = sorted(submissions, key = lambda s: -s.final_result)
194 return render(request, 'wtem/admin_report.csv', dict(
195 submissionsSet = SubmissionsSet(submissions),
196 exercise_ids = map(str, range(1,len(exercises)+1))
199 admin.site.register(Submission, SubmissionAdmin)
200 admin.site.register(Assignment)