Passed
Push — master ( b8e570...5310e7 )
by Peter
01:38
created

GradingTableView   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 60
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 15
c 3
b 0
f 0
dl 0
loc 60
rs 10

1 Method

Rating   Name   Duplication   Size   Complexity  
F get_context_data() 0 56 15
1
'''
2
OpenSubmit backend views that are not realized with Django admin.
3
'''
4
5
from django.views.generic import TemplateView, DetailView
6
from django.shortcuts import get_object_or_404
7
from django.contrib.auth.models import User
8
from django.contrib import messages
9
from django.shortcuts import redirect
10
from django.core.mail import send_mass_mail
11
from django.core.exceptions import ViewDoesNotExist
12
13
from formtools.preview import FormPreview
14
15
from opensubmit.models import Submission, Assignment, Course
16
from opensubmit.models.userprofile import move_user_data
17
from opensubmit.views.helpers import StaffRequiredMixin, ZipDownloadDetailView
18
19
20
class AssignmentArchiveView(StaffRequiredMixin, ZipDownloadDetailView):
21
    model = Assignment
22
23
    def fill_zip_file(self, z):
24
        assignment = self.object
25
        assignment.add_to_zipfile(z)
26
        subs = Submission.valid_ones.filter(assignment=assignment).order_by('submitter')
27
        for sub in subs:
28
            sub.add_to_zipfile(z)
29
        return assignment.directory_name()
30
31
32
class CourseArchiveView(StaffRequiredMixin, ZipDownloadDetailView):
33
    model = Course
34
35
    def fill_zip_file(self, z):
36
        course = self.object
37
        assignments = course.assignments.order_by('title')
38
        for ass in assignments:
39
            ass.add_to_zipfile(z)
40
            subs = ass.submissions.all().order_by('submitter')
41
            for sub in subs:
42
                sub.add_to_zipfile(z)
43
        return course.directory_name()
44
45
46
class PreviewView(StaffRequiredMixin, DetailView):
47
    template_name = 'file_preview.html'
48
    model = Submission
49
50
51
class DuplicatesView(StaffRequiredMixin, DetailView):
52
    template_name = 'duplicates.html'
53
    model = Assignment
54
55
56
class GradingTableView(StaffRequiredMixin, DetailView):
57
    template_name = 'gradingtable.html'
58
    model = Course
59
60
    def get_context_data(self, **kwargs):
61
        course = self.object
62
        assignments = course.assignments.all().order_by('title')
63
64
        # find all gradings per author and assignment
65
        author_submissions = {}
66
        for assignment in assignments:
67
            for submission in assignment.submissions.all().filter(state=Submission.CLOSED):
68
                for author in submission.authors.all():
69
                    # author_submissions is a dict mapping authors to another dict
70
                    # This second dict maps assignments to submissions (for this author)
71
                    # A tuple as dict key does not help here, since we want to iterate over the assignments later
72
                    if author not in list(author_submissions.keys()):
73
                        author_submissions[author] = {assignment.pk: submission}
74
                    else:
75
                        author_submissions[author][assignment.pk] = submission
76
        resulttable = []
77
        for author, ass2sub in list(author_submissions.items()):
78
            columns = []
79
            numpassed = 0
80
            numgraded = 0
81
            pointsum = 0
82
            columns.append(author.last_name if author.last_name else '')
83
            columns.append(author.first_name if author.first_name else '')
84
            columns.append(
85
                author.profile.student_id if author.profile.student_id else '')
86
            columns.append(
87
                author.profile.study_program if author.profile.study_program else '')
88
            # Process all assignments in the table order, once per author (loop above)
89
            for assignment in assignments:
90
                if assignment.pk in ass2sub:
91
                    # Ok, we have a submission for this author in this assignment
92
                    submission = ass2sub[assignment.pk]
93
                    if assignment.is_graded():
94
                        # is graded, make part of statistics
95
                        numgraded += 1
96
                        if submission.grading_means_passed():
97
                            numpassed += 1
98
                            try:
99
                                pointsum += int(str(submission.grading))
100
                            except Exception:
101
                                pass
102
                    # considers both graded and ungraded assignments
103
                    columns.append(submission.grading_value_text())
104
                else:
105
                    # No submission for this author in this assignment
106
                    # This may or may not be bad, so we keep it neutral here
107
                    columns.append('-')
108
            columns.append("%s / %s" % (numpassed, numgraded))
109
            columns.append("%u" % pointsum)
110
            resulttable.append(columns)
111
112
        context = super().get_context_data(**kwargs)
113
        context['assignments'] = assignments
114
        context['resulttable'] = sorted(resulttable)
115
        return context
116
117
118
class MergeUsersView(StaffRequiredMixin, TemplateView):
119
    template_name = 'mergeusers.html'
120
121
    def get_context_data(self, **kwargs):
122
        context = super().get_context_data(**kwargs)
123
        context['primary'] = get_object_or_404(User, pk=kwargs['primary_pk'])
124
        context['secondary'] = get_object_or_404(User, pk=kwargs['secondary_pk'])
125
        return context
126
127
    def post(self, request, *args, **kwargs):
128
        primary = get_object_or_404(User, pk=kwargs['primary_pk'])
129
        secondary = get_object_or_404(User, pk=kwargs['secondary_pk'])
130
        try:
131
            move_user_data(primary, secondary)
132
            messages.info(request, 'Submissions moved to user %u.' %
133
                          (primary.pk))
134
        except Exception:
135
            messages.error(
136
                request, 'Error during data migration, nothing changed.')
137
            return redirect('admin:index')
138
        messages.info(request, 'User %u updated, user %u deleted.' % (primary.pk, secondary.pk))
139
        secondary.delete()
140
        return redirect('admin:index')
141
142
143
class MailFormPreview(StaffRequiredMixin, FormPreview):
144
    form_template = 'mail_form.html'
145
    preview_template = 'mail_preview.html'
146
147
    def get_context(self, request, form):
148
        context = super().get_context(request, form)
149
        mailadrs_qs = self.state['receivers'].order_by('email').distinct().values('first_name', 'last_name', 'email')
150
        mailadrs = [mailadr for mailadr in mailadrs_qs]
151
        context['receivers'] = mailadrs
152
        context['sender'] = request.user
153
        return context
154
155
    def parse_params(self, request, *args, **kwargs):
156
        if 'user_list' in kwargs:
157
            id_list = [int(val) for val in kwargs['user_list'].split(',')]
158
            self.state['receivers'] = User.objects.filter(pk__in=id_list).distinct()
159
        elif 'course_id' in kwargs:
160
            course = get_object_or_404(Course, pk=kwargs['course_id'])
161
            self.state['receivers'] = User.objects.filter(profile__courses__pk=course.pk)
162
        else:
163
            raise ViewDoesNotExist
164
165
    def done(self, request, cleaned_data):
166
        from opensubmit.templatetags.projecttags import replace_macros
167
168
        tosend = [[replace_macros(cleaned_data['subject'], {'first_name': recv.first_name, 'last_name': recv.last_name}),
169
                   replace_macros(cleaned_data['message'], {'first_name': recv.first_name, 'last_name': recv.last_name}),
170
                   request.user.email,
171
                   [recv.email]] for recv in self.state['receivers']]
172
        sent = send_mass_mail(tosend, fail_silently=True)
173
        messages.add_message(request, messages.INFO, '%u message(s) sent.' % sent)
174
        return redirect('teacher:index')
175
176