Commit 9313f27f1e6b9418c8781d446f0bf6e644c6dee6

Authored by ifac0
1 parent 2ceb0949

modificações no app exam #171

courses/urls.py
@@ -26,5 +26,8 @@ urlpatterns = [ @@ -26,5 +26,8 @@ urlpatterns = [
26 26
27 url(r'^forum/', include('forum.urls', namespace = 'forum')), 27 url(r'^forum/', include('forum.urls', namespace = 'forum')),
28 url(r'^poll/', include('poll.urls', namespace = 'poll')), 28 url(r'^poll/', include('poll.urls', namespace = 'poll')),
  29 + url(r'^exam/', include('exam.urls', namespace = 'exam')),
  30 +
  31 +
29 32
30 ] 33 ]
1 from django.contrib import admin 1 from django.contrib import admin
2 2
3 -# Register your models here. 3 +from .models import Exam, Answer
  4 +
  5 +class ExamAdmin(admin.ModelAdmin):
  6 + list_display = ['name', 'slug','begin_date','limit_date']
  7 + search_fields = ['name','slug']
  8 +
  9 +class AnswerAdmin(admin.ModelAdmin):
  10 + list_display = ['answer','order']
  11 + search_fields = ['answer']
  12 +
  13 +admin.site.register(Exam, ExamAdmin)
  14 +admin.site.register(Answer, AnswerAdmin)
  1 +from django.utils.translation import ugettext_lazy as _
1 from django import forms 2 from django import forms
2 from .models import Exam 3 from .models import Exam
3 4
4 class ExamForm(forms.ModelForm): 5 class ExamForm(forms.ModelForm):
5 def clean_end_date(self): 6 def clean_end_date(self):
6 - beginDate = self.data['beginDate']  
7 - endDate = self.data['endDate'] 7 + begin_date = self.data['begin_date']
  8 + limit_date = self.data['limit_date']
8 9
9 - if beginDate and endDate and endDate < beginDate: 10 + if begin_date and limit_date and limit_date < begin_date:
10 raise forms.ValidationError(_('The end date may not be before the start date.')) 11 raise forms.ValidationError(_('The end date may not be before the start date.'))
11 return endDate 12 return endDate
12 13
13 - def clean_begin_date(self):  
14 - endDate = self.data['endDate']  
15 - beginDate = self.data['beginDate']  
16 -  
17 - if enDate and benginDate and beginDate <= endDate:  
18 - raise forms.ValidationError(_('The exam start date must be after the end of registration.'))  
19 - return beginDate  
20 -  
21 - def clean_end_date(self):  
22 - beginDate = self.data['beginDate']  
23 - endDate = self.data['endDate']  
24 -  
25 - if beginDate and endDate and endDate < beginDate:  
26 - raise forms.ValidationError(_('The finish date may not be before the start date.'))  
27 - return end_date  
28 -  
29 -  
30 14
31 class Meta: 15 class Meta:
32 model = Exam 16 model = Exam
33 - fields = ['name','beginDate','endDate'] 17 + fields = ['name','begin_date','limit_date']
34 18
35 widgets = { 19 widgets = {
36 'name': forms.TextInput(attrs={'placeholder': 'Exam?'}), 20 'name': forms.TextInput(attrs={'placeholder': 'Exam?'}),
37 - 'beginDate': forms.DateTimeInput(attrs={'placeholder': 'Start date to resolve the exam'}),  
38 - 'endDate': forms.DateTimeInput(attrs={'placeholder': 'Finish date permited to resolve the exam'}), 21 + 'begin_date': forms.DateTimeInput(attrs={'placeholder': _('Start date to resolve the exam')}),
  22 + 'limit_date': forms.DateTimeInput(attrs={'placeholder': _('Finish date permited to resolve the exam')}),
39 } 23 }
exam/models.py
@@ -5,23 +5,19 @@ from users.models import User @@ -5,23 +5,19 @@ from users.models import User
5 from core.models import Resource 5 from core.models import Resource
6 from courses.models import Activity 6 from courses.models import Activity
7 7
8 -  
9 -  
10 -class Exam(models.Model):  
11 - name = models.CharField(_('Name'), max_length = 100)  
12 - beginDate = models.DateTimeField(_('Start Date'), auto_now_add = True)  
13 - endDate = models.DateTimeField(_('Date of last update'), auto_now=True) 8 +class Exam(Activity):
  9 + begin_date = models.DateField(_('Begin of Course Date'))
14 10
15 class Meta: 11 class Meta:
16 - #ordering = ('create_date','name')  
17 verbose_name = _('Exam') 12 verbose_name = _('Exam')
18 verbose_name_plural = _('Exams') 13 verbose_name_plural = _('Exams')
19 14
20 def __str__(self): 15 def __str__(self):
21 return str(self.name) + str("/") + str(self.topic) 16 return str(self.name) + str("/") + str(self.topic)
22 17
  18 +
23 class Answer(models.Model): 19 class Answer(models.Model):
24 - answer = models.CharField(_("Answer"), max_length = 200) 20 + answer = models.CharField(_("Answer"), max_length = 300)
25 order = models.PositiveSmallIntegerField(_("Order")) 21 order = models.PositiveSmallIntegerField(_("Order"))
26 exam = models.ForeignKey(Exam, verbose_name = _('Answers'), related_name='answers') 22 exam = models.ForeignKey(Exam, verbose_name = _('Answers'), related_name='answers')
27 23
exam/permisissions.py
@@ -1,12 +0,0 @@ @@ -1,12 +0,0 @@
1 -from rolepermissions.permissions import register_object_checker  
2 -from amadeus.roles import SystemAdmin  
3 -  
4 -@register_object_checker()  
5 -def edit_exam(role, user, exam):  
6 - if (role == SystemAdmin):  
7 - return True  
8 -  
9 - if (user in exam.topic.subject.professors.all()):  
10 - return True  
11 -  
12 - return False  
exam/permissions.py 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +from rolepermissions.permissions import register_object_checker
  2 +from amadeus.roles import SystemAdmin
  3 +
  4 +@register_object_checker()
  5 +def edit_exam(role, user, exam):
  6 + if (role == SystemAdmin):
  7 + return True
  8 +
  9 + if (user in exam.topic.subject.professors.all()):
  10 + return True
  11 +
  12 + return False
exam/templates/exam/create.html 0 → 100644
exam/templates/exam/form_exam.html
@@ -1,60 +0,0 @@ @@ -1,60 +0,0 @@
1 -<div class="panel panel-info">  
2 - <div class="panel-heading">  
3 - <h3 class="panel-title">New Exam</h3>  
4 - </div>  
5 - <div class="panel-body">  
6 - <form class="form-horizontal">  
7 -  
8 - <div class="form-group">  
9 - <label for="examName" class="col-md-2 control-label">Exam Name</label>  
10 -  
11 - <div class="col-md-10">  
12 - <input type="text" class="form-control" id="examName" placeholder="Exam Name">  
13 - </div>  
14 -  
15 -  
16 - </div>  
17 - <div class="form-group">  
18 - <label for="Date" class="col-md-2 control-label">Exam Period</label>  
19 - <div class="col-md-5">  
20 - <input type="date" class="form-control" id="beginDate" placeholder="Begin Date">  
21 -  
22 - </div>  
23 - <div class="col-md-5">  
24 - <input type="date" class="form-control" id="endDate" placeholder="End Date">  
25 -  
26 - </div>  
27 - </div>  
28 - <div class="form-group">  
29 - <label for="deadline" class="col-md-2 control-label">Allow submissions after deadline?</label>  
30 - <div class="col-md-10">  
31 - <label>  
32 - <input type="checkbox">  
33 - </label>  
34 - </div>  
35 - </div>  
36 - <div class="form-group">  
37 - <label for="questionType" class="col-md-2 control-label">Question Type</label>  
38 - <div class="col-md-10">  
39 - <select id="questionType" class="form-control" onchange="showDiv (this)">  
40 - <option selected disabled>Question Type</option>  
41 - <option value="0">Multiple Choice</option>  
42 - <option value="1">True or False</option>  
43 - <option value="2">Gap Filling</option>  
44 - <option value="3">Discursive Question</option>  
45 - </select>  
46 - </div>  
47 - </div>  
48 - </form>  
49 - </div>  
50 -</div>  
51 -  
52 -<script>  
53 - function showDiv (elem) {  
54 - if (elem.value == 0) {  
55 - document.getElementById('multipleChoice').style.display = "block";  
56 - } else if (elem.value == 1) {  
57 - document.getElementById('trueOrFalse').style.display = "block";  
58 - }  
59 - }  
60 -</script>  
exam/templates/exam/remove.html 0 → 100644
exam/templates/exam/update.html 0 → 100644
exam/templates/exam/view.html 0 → 100644
@@ -3,7 +3,8 @@ from django.conf.urls import url @@ -3,7 +3,8 @@ from django.conf.urls import url
3 from . import views 3 from . import views
4 4
5 urlpatterns = [ 5 urlpatterns = [
6 - url(r'^create/(?P<slug>[\w\-_]+)/$', views.CreateExam.as_view(), name='create_poll'),  
7 - url(r'^update/(?P<slug>[\w\-_]+)/$', views.UpdateExam.as_view(), name='update_poll'),  
8 - 6 + url(r'^create/(?P<slug>[\w\-_]+)/$', views.CreateExam.as_view(), name='create_exam'),
  7 + url(r'^update/(?P<slug>[\w\-_]+)/$', views.UpdateExam.as_view(), name='update_exam'),
  8 + url(r'^view/(?P<slug>[\w\-_]+)/$', views.ViewExam.as_view(), name='view_exam'),
  9 + url(r'^delete/(?P<slug>[\w\-_]+)/$', views.DeleteExam.as_view(), name='delete_exam'),
9 ] 10 ]
@@ -8,6 +8,7 @@ from django.core.urlresolvers import reverse_lazy @@ -8,6 +8,7 @@ from django.core.urlresolvers import reverse_lazy
8 from django.utils.translation import ugettext_lazy as _ 8 from django.utils.translation import ugettext_lazy as _
9 from rolepermissions.verifications import has_role 9 from rolepermissions.verifications import has_role
10 from rolepermissions.verifications import has_object_permission 10 from rolepermissions.verifications import has_object_permission
  11 +from django.db.models import Q
11 # from django.views.generic.edit import FormMixin 12 # from django.views.generic.edit import FormMixin
12 13
13 from .forms import ExamForm 14 from .forms import ExamForm
@@ -16,34 +17,76 @@ from core.mixins import NotificationMixin @@ -16,34 +17,76 @@ from core.mixins import NotificationMixin
16 from users.models import User 17 from users.models import User
17 from courses.models import Course, Topic 18 from courses.models import Course, Topic
18 19
19 -class CreateExam(LoginRequiredMixin,generic.CreateView): 20 +class ViewExam(LoginRequiredMixin,generic.DetailView):
20 21
21 - login_url = reverse_lazy("core:home")  
22 - redirect_field_name = 'next'  
23 model = Exam 22 model = Exam
24 - form_class = PollForm  
25 context_object_name = 'exam' 23 context_object_name = 'exam'
26 - template_name = 'exam/form_exam.html'  
27 - success_url = reverse_lazy('core:home') 24 + template_name = 'exam/view.html'
  25 +
  26 + def get_object(self, queryset=None):
  27 + return get_object_or_404(Exam, slug = self.kwargs.get('slug'))
  28 +
  29 + def form_invalid(self, form,**kwargs):
  30 + context = super(ViewExam, self).form_invalid(form)
  31 + answers = {}
  32 + for key in self.request.POST:
  33 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key!= 'begin_date' and key != 'limit_date' and key != 'all_students' and key != 'students'):
  34 + answers[key] = self.request.POST[key]
  35 +
  36 + keys = sorted(answers)
  37 + context.context_data['answers'] = answers
  38 + context.context_data['keys'] = keys
  39 + return context
28 40
29 def form_valid(self, form): 41 def form_valid(self, form):
30 - self.object = form.save(commit = False)  
31 - topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))  
32 - self.object.topic = topic  
33 - self.object.save() 42 + exam = self.object
  43 + exam = form.save(commit = False)
  44 + exam.answers.all().delete()
  45 + exam.save()
  46 +
34 47
35 for key in self.request.POST: 48 for key in self.request.POST:
36 - if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'beginDate' and key != 'endDate'):  
37 - answer = Answer(answer=self.request.POST[key],order=key,poll=self.object) 49 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'begin_date' and key != 'limit_date' and key != 'all_students' and key != 'students'):
  50 + answer = Answer(answer=self.request.POST[key],order=key,exam=exam)
38 answer.save() 51 answer.save()
39 52
40 - return super(CreateExam, self).form_valid(form) 53 + return super(ViewExam, self).form_valid(form)
  54 +
  55 + def get_context_data(self, **kwargs):
  56 + context = super(ViewExam, self).get_context_data(**kwargs)
  57 + exam = self.object
  58 + context['course'] = exam.topic.subject.course
  59 + context['subject'] = exam.topic.subject
  60 + context['subjects'] = exam.topic.subject.course.subjects.all()
  61 +
  62 + answers = {}
  63 + for answer in exam.answers.all():
  64 + answers[answer.order] = answer.answer
  65 +
  66 + keys = sorted(answers)
  67 + context['answers'] = answers
  68 + context['keys'] = keys
  69 +
  70 + print (context)
  71 + return context
  72 +
  73 +
  74 +class CreateExam(LoginRequiredMixin,HasRoleMixin,generic.CreateView):
  75 +
  76 + allowed_roles = ['professor', 'system_admin']
  77 + login_url = reverse_lazy("core:home")
  78 + redirect_field_name = 'next'
  79 + model = Exam
  80 + form_class = ExamForm
  81 + context_object_name = 'exam'
  82 + template_name = 'exam/create.html'
  83 + success_url = reverse_lazy('core:home')
41 84
42 def form_invalid(self, form,**kwargs): 85 def form_invalid(self, form,**kwargs):
43 context = super(CreateExam, self).form_invalid(form) 86 context = super(CreateExam, self).form_invalid(form)
44 answers = {} 87 answers = {}
45 for key in self.request.POST: 88 for key in self.request.POST:
46 - if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'beginDate' and key != 'endDate'): 89 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'begin_date' and key != 'limit_date' and key != 'all_students' and key != 'students'):
47 answers[key] = self.request.POST[key] 90 answers[key] = self.request.POST[key]
48 91
49 keys = sorted(answers) 92 keys = sorted(answers)
@@ -51,47 +94,115 @@ class CreateExam(LoginRequiredMixin,generic.CreateView): @@ -51,47 +94,115 @@ class CreateExam(LoginRequiredMixin,generic.CreateView):
51 context.context_data['keys'] = keys 94 context.context_data['keys'] = keys
52 return context 95 return context
53 96
54 -class UpdateExam(LoginRequiredMixin,generic.UpdateView): 97 + def form_valid(self, form):
  98 + self.object = form.save(commit = False)
  99 + topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
  100 + self.object.topic = topic
  101 + self.object.save()
55 102
  103 + for key in self.request.POST:
  104 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'begin_date' and key != 'limit_date' and key != 'all_students' and key != 'students'):
  105 + answer = Answer(answer=self.request.POST[key],order=key,exam=self.object)
  106 + answer.save()
  107 +
  108 + return super(CreatePoll, self).form_valid(form)
  109 +
  110 + def get_context_data(self, **kwargs):
  111 + context = super(CreateExam, self).get_context_data(**kwargs)
  112 + topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
  113 + context['course'] = topic.subject.course
  114 + context['subject'] = topic.subject
  115 + context['subjects'] = topic.subject.course.subjects.all()
  116 + return context
  117 +
  118 +class UpdateExam(LoginRequiredMixin,HasRoleMixin,generic.UpdateView):
  119 +
  120 + allowed_roles = ['professor', 'system_admin']
56 login_url = reverse_lazy("core:home") 121 login_url = reverse_lazy("core:home")
57 redirect_field_name = 'next' 122 redirect_field_name = 'next'
58 model = Exam 123 model = Exam
59 form_class = ExamForm 124 form_class = ExamForm
60 context_object_name = 'exam' 125 context_object_name = 'exam'
61 - template_name = 'poll/form_exam.html' 126 + template_name = 'exam/update.html'
62 success_url = reverse_lazy('core:home') 127 success_url = reverse_lazy('core:home')
63 128
64 def dispatch(self, *args, **kwargs): 129 def dispatch(self, *args, **kwargs):
65 - poll = get_object_or_404(Poll, slug = self.kwargs.get('slug'))  
66 - 130 + exam = get_object_or_404(Exam, slug = self.kwargs.get('slug'))
67 if(not has_object_permission('edit_exam', self.request.user, exam)): 131 if(not has_object_permission('edit_exam', self.request.user, exam)):
68 return self.handle_no_permission() 132 return self.handle_no_permission()
69 - return super(UpdateExam, self).dispatch(*args, **kwargs) 133 + return super(UpdatePoll, self).dispatch(*args, **kwargs)
70 134
71 def get_object(self, queryset=None): 135 def get_object(self, queryset=None):
72 - return get_object_or_404(Poll, slug = self.kwargs.get('slug')) 136 + return get_object_or_404(Exam, slug = self.kwargs.get('slug'))
  137 +
  138 + def form_invalid(self, form,**kwargs):
  139 + context = super(UpdateExam, self).form_invalid(form)
  140 + answers = {}
  141 + for key in self.request.POST:
  142 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'begin_date' and key != 'limit_date' and key != 'all_students' and key != 'students'):
  143 + answers[key] = self.request.POST[key]
  144 +
  145 + keys = sorted(answers)
  146 + context.context_data['answers'] = answers
  147 + context.context_data['keys'] = keys
  148 + return context
73 149
74 def form_valid(self, form): 150 def form_valid(self, form):
75 - poll = self.object  
76 - poll = form.save(commit = False)  
77 - poll.answers.all().delete()  
78 - poll.save() 151 + exam = self.object
  152 + exam = form.save(commit = False)
  153 + exam.answers.all().delete()
  154 + exam.save()
  155 +
79 156
80 for key in self.request.POST: 157 for key in self.request.POST:
81 - if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'beginDate' and key != 'endDate'): 158 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'begin_date' and key != 'limit_date' and key != 'all_students' and key != 'students'):
82 answer = Answer(answer=self.request.POST[key],order=key,exam=exam) 159 answer = Answer(answer=self.request.POST[key],order=key,exam=exam)
83 answer.save() 160 answer.save()
84 161
85 return super(UpdateExam, self).form_valid(form) 162 return super(UpdateExam, self).form_valid(form)
86 163
87 - def form_invalid(self, form,**kwargs):  
88 - context = super(UpdateExam, self).form_invalid(form) 164 + def get_context_data(self, **kwargs):
  165 + context = super(UpdateExam, self).get_context_data(**kwargs)
  166 + exam = self.object
  167 + context['course'] = exam.topic.subject.course
  168 + context['subject'] = exam.topic.subject
  169 + context['subjects'] = exam.topic.subject.course.subjects.all()
  170 +
89 answers = {} 171 answers = {}
90 - for key in self.request.POST:  
91 - if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'beginDate' and key != 'endDate'):  
92 - answers[key] = self.request.POST[key] 172 + for answer in exam.answers.all():
  173 + # print (key.answer)
  174 + answers[answer.order] = answer.answer
93 175
94 keys = sorted(answers) 176 keys = sorted(answers)
95 - context.context_data['answers'] = answers  
96 - context.context_data['keys'] = keys 177 + context['answers'] = answers
  178 + context['keys'] = keys
  179 +
  180 + return context
  181 +
  182 +class DeleteExam(LoginRequiredMixin, HasRoleMixin, generic.DeleteView):
  183 +
  184 + allowed_roles = ['professor', 'system_admin']
  185 + login_url = reverse_lazy("core:home")
  186 + redirect_field_name = 'next'
  187 + model = Exam
  188 + template_name = 'exam/remove.html'
  189 +
  190 + def dispatch(self, *args, **kwargs):
  191 + exam = get_object_or_404(Exam, slug = self.kwargs.get('slug'))
  192 + if(not has_object_permission('delete_exam', self.request.user, exam)):
  193 + return self.handle_no_permission()
  194 + return super(DeleteExam, self).dispatch(*args, **kwargs)
  195 +
  196 +
  197 + def get_context_data(self, **kwargs):
  198 + context = super(DeleteExam, self).get_context_data(**kwargs)
  199 + context['course'] = self.object.topic.subject.course
  200 + context['subject'] = self.object.topic.subject
  201 + context['exam'] = self.object
  202 + context['subjects'] = self.object.topic.subject.course.subjects.filter(Q(visible=True) | Q(professors__in=[self.request.user]))
  203 + if (has_role(self.request.user,'system_admin')):
  204 + context['subjects'] = self.object.topic.subject.course.subjects.all()
97 return context 205 return context
  206 +
  207 + def get_success_url(self):
  208 + return reverse_lazy('course:view_topic', kwargs={'slug' : self.object.topic.slug})