Commit ab2f3a0c9530aa4f6960efc0709cc17f58dcee01
Exists in
master
and in
5 other branches
Merge branch 'dev' of https://github.com/amadeusproject/amadeuslms into dev
Showing
18 changed files
with
239 additions
and
148 deletions
Show diff stats
amadeus/settings.py
courses/urls.py
@@ -26,5 +26,8 @@ urlpatterns = [ | @@ -26,5 +26,8 @@ urlpatterns = [ | ||
26 | url(r'^subjects/categories$',views.IndexSubjectCategoryView.as_view(), name='subject_category_index'), | 26 | url(r'^subjects/categories$',views.IndexSubjectCategoryView.as_view(), name='subject_category_index'), |
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 | ] |
exam/admin.py
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) |
exam/forms.py
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 |
@@ -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/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/urls.py
@@ -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 | ] |
exam/views.py
@@ -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}) |
@@ -0,0 +1,34 @@ | @@ -0,0 +1,34 @@ | ||
1 | +# -*- coding: utf-8 -*- | ||
2 | +# Generated by Django 1.10 on 2016-10-13 16:12 | ||
3 | +from __future__ import unicode_literals | ||
4 | + | ||
5 | +from django.db import migrations, models | ||
6 | +import django.db.models.deletion | ||
7 | +import files.models | ||
8 | + | ||
9 | + | ||
10 | +class Migration(migrations.Migration): | ||
11 | + | ||
12 | + initial = True | ||
13 | + | ||
14 | + dependencies = [ | ||
15 | + ('core', '0002_mymetype'), | ||
16 | + ('courses', '0004_auto_20161011_1951'), | ||
17 | + ] | ||
18 | + | ||
19 | + operations = [ | ||
20 | + migrations.CreateModel( | ||
21 | + name='TopicFile', | ||
22 | + fields=[ | ||
23 | + ('material_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Material')), | ||
24 | + ('description', models.TextField(blank=True, verbose_name='Description')), | ||
25 | + ('file_url', models.FileField(upload_to=files.models.file_path, verbose_name='File')), | ||
26 | + ('file_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='topic_files', to='core.MymeType', verbose_name='Type file')), | ||
27 | + ], | ||
28 | + options={ | ||
29 | + 'verbose_name': 'File', | ||
30 | + 'verbose_name_plural': 'Files', | ||
31 | + }, | ||
32 | + bases=('courses.material',), | ||
33 | + ), | ||
34 | + ] |
files/models.py
1 | from django.db import models | 1 | from django.db import models |
2 | from django.utils.translation import ugettext_lazy as _ | 2 | from django.utils.translation import ugettext_lazy as _ |
3 | - | ||
4 | -from courses.models import Activity | 3 | +from core.models import MymeType |
4 | +from courses.models import Material | ||
5 | 5 | ||
6 | """ | 6 | """ |
7 | Function to return the path where the file should be saved | 7 | Function to return the path where the file should be saved |
@@ -14,8 +14,11 @@ def file_path(instance, filename): | @@ -14,8 +14,11 @@ def file_path(instance, filename): | ||
14 | It's one kind of activity available for a Topic. | 14 | It's one kind of activity available for a Topic. |
15 | It's like a support material for the students. | 15 | It's like a support material for the students. |
16 | """ | 16 | """ |
17 | -class TopicFiles(Activity): | 17 | +class TopicFile(Material): |
18 | + description = models.TextField(_('Description'), blank=True) | ||
18 | file_url = models.FileField(verbose_name = _("File"), upload_to = file_path) | 19 | file_url = models.FileField(verbose_name = _("File"), upload_to = file_path) |
20 | + file_type = models.ForeignKey(MymeType, verbose_name=_('Type file'), related_name='topic_files') | ||
21 | + | ||
19 | 22 | ||
20 | class Meta: | 23 | class Meta: |
21 | verbose_name = _("File") | 24 | verbose_name = _("File") |
links/tests.py
1 | from django.test import TestCase,Client | 1 | from django.test import TestCase,Client |
2 | from django.core.urlresolvers import reverse | 2 | from django.core.urlresolvers import reverse |
3 | from rolepermissions.shortcuts import assign_role | 3 | from rolepermissions.shortcuts import assign_role |
4 | +from django.utils.translation import ugettext_lazy as _ | ||
4 | 5 | ||
5 | from users.models import User | 6 | from users.models import User |
6 | from .models import * | 7 | from .models import * |
8 | +from .forms import * | ||
7 | 9 | ||
8 | # Create your tests here. | 10 | # Create your tests here. |
9 | class LinkTestCase(TestCase): | 11 | class LinkTestCase(TestCase): |
@@ -28,8 +30,10 @@ class LinkTestCase(TestCase): | @@ -28,8 +30,10 @@ class LinkTestCase(TestCase): | ||
28 | "link" : 'teste.com' | 30 | "link" : 'teste.com' |
29 | } | 31 | } |
30 | response = self.client.post(url, data) | 32 | response = self.client.post(url, data) |
33 | + #self.assertEqual(response.status_code, 200) | ||
34 | + self.assertFormError(response,'form',"link",_("Please enter a valid URL")) | ||
31 | self.assertEqual(Link.objects.all().count(),links+1) #After creating one link, if OK, the link was created successfully. | 35 | self.assertEqual(Link.objects.all().count(),links+1) #After creating one link, if OK, the link was created successfully. |
32 | - self.assertEqual(response.status_code, 200) | 36 | + self.assertEqual(response.status_code, 302) #If OK, User is getting redirected correctly. |
33 | self.assertTemplateUsed(template_name = 'links/link_modal.html') | 37 | self.assertTemplateUsed(template_name = 'links/link_modal.html') |
34 | # def test_update_link(): | 38 | # def test_update_link(): |
35 | # pass | 39 | # pass |
@@ -41,8 +45,11 @@ class LinkTestCase(TestCase): | @@ -41,8 +45,11 @@ class LinkTestCase(TestCase): | ||
41 | ) | 45 | ) |
42 | self.client.login(username='user', password = 'testing') | 46 | self.client.login(username='user', password = 'testing') |
43 | links = Link.objects.all().count() | 47 | links = Link.objects.all().count() |
48 | + deletedlink = Link.objects.get(name = self.link.name) | ||
44 | url = reverse('course:delete_link',kwargs={'linkname': self.link.name}) | 49 | url = reverse('course:delete_link',kwargs={'linkname': self.link.name}) |
45 | self.assertEqual(Link.objects.all().count(),links) | 50 | self.assertEqual(Link.objects.all().count(),links) |
46 | - response = self.client.get(url) | ||
47 | - self.assertEqual(Link.objects.all().count(),links - 1) | ||
48 | - self.assertEqual(response.status_code, 200) | 51 | + response = self.client.post(url) |
52 | + self.assertEqual(Link.objects.all().count(),links - 1) #Objeto removido | ||
53 | + self.assertEqual(Link.objects.filter(name= deletedlink.name).exists(),False) #Objeto removido e sua não-existência verificada | ||
54 | + #self.assertEqual(Link.objects.filter(name= deletedlink.name).exists(),True) #Objeto removido e sua existência verificada, se ERRO, objeto foi removido com sucesso! | ||
55 | + self.assertEqual(response.status_code, 302) #If OK, User is getting redirected correctly. |
links/views.py
@@ -12,7 +12,7 @@ from .forms import * | @@ -12,7 +12,7 @@ from .forms import * | ||
12 | class CreateLink(generic.CreateView): | 12 | class CreateLink(generic.CreateView): |
13 | template_name = 'links/link_modal.html' | 13 | template_name = 'links/link_modal.html' |
14 | form_class = CreateLinkForm | 14 | form_class = CreateLinkForm |
15 | - success_url = reverse_lazy() | 15 | + success_url = reverse_lazy('course:manage') |
16 | context_object_name = 'links' | 16 | context_object_name = 'links' |
17 | 17 | ||
18 | def form_valid(self, form): | 18 | def form_valid(self, form): |
@@ -29,7 +29,7 @@ def deleteLink(request,linkname): | @@ -29,7 +29,7 @@ def deleteLink(request,linkname): | ||
29 | link = get_object_or_404(Link,name = linkname) | 29 | link = get_object_or_404(Link,name = linkname) |
30 | link.delete() | 30 | link.delete() |
31 | messages.success(request,_("Link deleted Successfully!")) | 31 | messages.success(request,_("Link deleted Successfully!")) |
32 | - return redirect('course:update_topic') | 32 | + return redirect('course:manage') |
33 | class UpdateLink(generic.UpdateView): | 33 | class UpdateLink(generic.UpdateView): |
34 | template_name = 'links/' | 34 | template_name = 'links/' |
35 | form_class = UpdateLinkForm | 35 | form_class = UpdateLinkForm |