Passed
Push — master ( a505d5...8178ea )
by Peter
01:25
created

CoursesView.form_valid()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
1
from datetime import datetime
2
import json
3
4
from django.views.generic import TemplateView, RedirectView, ListView, DetailView
5
from django.views.generic.edit import UpdateView
6
from django.shortcuts import redirect
7
from django.contrib import auth, messages
8
from django.contrib.auth.decorators import login_required
9
from django.utils.decorators import method_decorator
10
from django.core.urlresolvers import reverse_lazy
11
from django.forms.models import modelform_factory, model_to_dict
12
from django.core.exceptions import PermissionDenied
13
14
from opensubmit.forms import SettingsForm
15
from opensubmit.models import UserProfile, Submission, TestMachine, Course
16
from opensubmit.models.userprofile import db_fixes
17
18
19
class IndexView(TemplateView):
20
    template_name = 'index.html'
21
22
    def get(self, request):
23
        if request.user.is_authenticated():
24
            return redirect('dashboard')
25
        else:
26
            return super(IndexView, self).get(request)
27
28
29
@method_decorator(login_required, name='dispatch')
30
class LogoutView(RedirectView):
31
    '''
32
    TODO: Not needed with Django 1.11, which has own LogoutView.
33
    '''
34
    permanent = False
35
    pattern_name = 'index'
36
37
    def get(self, request):
38
        auth.logout(request)
39
        return super().get(request)
40
41
42
@method_decorator(login_required, name='dispatch')
43
class SettingsView(UpdateView):
44
    template_name = 'settings.html'
45
    form_class = SettingsForm
46
    success_url = reverse_lazy('dashboard')
47
48
    def form_valid(self, form):
49
        messages.info(self.request, 'User settings saved.')
50
        return super().form_valid(form)
51
52
    def get_object(self, queryset=None):
53
        return self.request.user
54
55
56
@method_decorator(login_required, name='dispatch')
57
class CoursesView(UpdateView):
58
    template_name = 'courses.html'
59
    form_class = modelform_factory(UserProfile, fields=['courses'])
60
    success_url = reverse_lazy('dashboard')
61
62
    def form_valid(self, form):
63
        messages.info(self.request, 'Your choice of courses was saved.')
64
        return super().form_valid(form)
65
66
    def get_object(self, queryset=None):
67
        return self.request.user.profile
68
69
    def get_context_data(self, **kwargs):
70
        context = super().get_context_data(**kwargs)
71
        context['courses'] = self.request.user.profile.user_courses()
72
        return context
73
74
75
@method_decorator(login_required, name='dispatch')
76
class ArchiveView(ListView):
77
    template_name = 'archive.html'
78
79
    def get_queryset(self):
80
        archived = self.request.user.authored.all().exclude(assignment__course__active=False).filter(state=Submission.WITHDRAWN).order_by('-created')
81
        return archived
82
83
84
@method_decorator(login_required, name='dispatch')
85
class DashboardView(TemplateView):
86
    template_name = 'dashboard.html'
87
88
    def get_context_data(self, **kwargs):
89
        context = super().get_context_data(**kwargs)
90
91
        # Student submissions under validation / grading
92
        context['subs_in_progress'] = self.request.user.authored.all(). \
93
            exclude(assignment__course__active=False). \
94
            exclude(state=Submission.RECEIVED). \
95
            exclude(state=Submission.WITHDRAWN). \
96
            exclude(state=Submission.CLOSED). \
97
            exclude(state=Submission.CLOSED_TEST_FULL_PENDING). \
98
            order_by('-created')
99
100
        # Closed student submissions, graded ones first
101
        context['subs_finished'] = self.request.user.authored.all(). \
102
            exclude(assignment__course__active=False). \
103
            filter(state__in=[Submission.CLOSED, Submission.CLOSED_TEST_FULL_PENDING]). \
104
            order_by('-assignment__gradingScheme', '-created')
105
106
        context['machines'] = TestMachine.objects.filter(enabled=True)
107
        context['today'] = datetime.now()
108
        context['user'] = self.request.user
109
        return context
110
111
    def get(self, request):
112
        # Check and fix database on lower levels for the current user
113
        db_fixes(request.user)
114
115
        # LTI keys and passwords are defined per course
116
        # We use this here to register students automatically for
117
        # courses based on their LTI credentials.
118
        # Note: Authentication is already over here.
119
        if 'passthroughauth' in request.session:
120
            if 'ltikey' in request.session['passthroughauth']:
121
                try:
122
                    ltikey = request.session['passthroughauth']['ltikey']
123
                    request.session['ui_disable_logout'] = True
124
                    course = Course.objects.get(lti_key=ltikey)
125
                    request.user.profile.courses.add(course)
126
                    request.user.profile.save()
127
                except Exception:
128
                    # LTI-based course registration is only a comfort function,
129
                    # so we should not crash the app if that goes wrong
130
                    pass
131
132
        # This is the first view than can check
133
        # if the user settings are complete.
134
        # This depends on the amount of information the authentication provider
135
        # already handed in.
136
        # If incomplete, then we drop annyoing popups until the user gives up.
137
        settingsform = SettingsForm(model_to_dict(request.user), instance=request.user)
138
        if not settingsform.is_valid():
139
            messages.error(request, "Your user settings are incomplete.")
140
141
        return super().get(request)
142
143
144
@method_decorator(login_required, name='dispatch')
145
class SubmissionDetailsView(DetailView):
146
    template_name = 'details.html'
147
    model = Submission
148
149
    def get_object(self, queryset=None):
150
        subm = super().get_object(queryset)
151
        # only authors should be able to look into submission details
152
        if not (self.request.user in subm.authors.all() or self.request.user.is_staff):
153
            raise PermissionDenied()
154
        return subm
155
156
157
@method_decorator(login_required, name='dispatch')
158
class MachineDetailsView(DetailView):
159
    template_name = 'machine.html'
160
    model = TestMachine
161
162
    def get_context_data(self, **kwargs):
163
        context = super().get_context_data(**kwargs)
164
        try:
165
            context['config'] = json.loads(self.object.config)
166
        except Exception:
167
            context['config'] = []
168
        context['queue'] = Submission.pending_student_tests.all()
169
        context['additional'] = len(Submission.pending_full_tests.all())
170
        return context
171