Commit efc480e12d8626f13b02413c7aeb2b77e53acf0d
1 parent
3894ffb6
Exists in
master
and in
5 other branches
Criado as páginas de atualizar e deletar curso
Showing
9 changed files
with
198 additions
and
85 deletions
Show diff stats
courses/forms.py
1 | + | |
1 | 2 | from django import forms |
2 | 3 | from django.utils.translation import ugettext_lazy as _ |
3 | 4 | from .models import Category, Course, Subject, Topic |
4 | -import datetime | |
5 | 5 | |
6 | 6 | class CategoryForm(forms.ModelForm): |
7 | 7 | |
... | ... | @@ -26,9 +26,6 @@ class CourseForm(forms.ModelForm): |
26 | 26 | return end_register_date |
27 | 27 | |
28 | 28 | def clean_init_date(self): |
29 | - # print(dir(self)) | |
30 | - print (self.data) | |
31 | - print (self.cleaned_data) | |
32 | 29 | end_register_date = self.data['end_register_date'] |
33 | 30 | init_date = self.data['init_date'] |
34 | 31 | |
... | ... | @@ -78,6 +75,47 @@ class CourseForm(forms.ModelForm): |
78 | 75 | 'content': forms.Textarea(attrs={'cols': 80, 'rows': 5}), |
79 | 76 | } |
80 | 77 | |
78 | +class UpdateCourseForm(CourseForm): | |
79 | + def __init__(self, *args, **kwargs): | |
80 | + super(UpdateCourseForm, self).__init__(*args, **kwargs) | |
81 | + self.fields["students"].required = False | |
82 | + | |
83 | + class Meta: | |
84 | + model = Course | |
85 | + fields = ('name', 'objectivies', 'content', 'max_students', 'init_register_date', 'end_register_date', | |
86 | + 'init_date', 'end_date', 'image', 'category','students',) | |
87 | + labels = { | |
88 | + 'name': _('Name'), | |
89 | + 'objectivies': _('Objectives'), | |
90 | + 'content': _('Content'), | |
91 | + 'max_students': _('Number of studets maximum'), | |
92 | + 'init_register_date': _('Course registration start date'), | |
93 | + 'end_register_date': _('Course registration end date'), | |
94 | + 'init_date': _('Course start date'), | |
95 | + 'end_date': _('Course end date'), | |
96 | + 'image': _('Image'), | |
97 | + 'category': _('Category'), | |
98 | + 'students': _('Student'), | |
99 | + } | |
100 | + help_texts = { | |
101 | + 'name': _('Course name'), | |
102 | + 'objectivies': _('Course objective'), | |
103 | + 'content': _('Course modules'), | |
104 | + 'max_students': _('Max number of students that a class can have'), | |
105 | + 'init_register_date': _('Date that starts the registration period of the course (dd/mm/yyyy)'), | |
106 | + 'end_register_date': _('Date that ends the registration period of the course (dd/mm/yyyy)'), | |
107 | + 'init_date': _('Date that the course starts (dd/mm/yyyy)'), | |
108 | + 'end_date': _('Date that the course ends (dd/mm/yyyy)'), | |
109 | + 'image': _('Representative image of the course'), | |
110 | + 'category': _('Category which the course belongs'), | |
111 | + 'students': _("Course's Students"), | |
112 | + } | |
113 | + widgets = { | |
114 | + 'categoy': forms.Select(), | |
115 | + 'objectivies': forms.Textarea(attrs={'cols': 80, 'rows': 5}), | |
116 | + 'content': forms.Textarea(attrs={'cols': 80, 'rows': 5}), | |
117 | + } | |
118 | + | |
81 | 119 | class SubjectForm(forms.ModelForm): |
82 | 120 | |
83 | 121 | class Meta: | ... | ... |
courses/permissions.py
... | ... | @@ -30,3 +30,23 @@ def delete_subject(role, user, subject): |
30 | 30 | return True |
31 | 31 | |
32 | 32 | return False |
33 | + | |
34 | +@register_object_checker() | |
35 | +def update_course(role, user, course): | |
36 | + if (role == SystemAdmin): | |
37 | + return True | |
38 | + | |
39 | + if (user in course.professors.all()): | |
40 | + return True | |
41 | + | |
42 | + return False | |
43 | + | |
44 | +@register_object_checker() | |
45 | +def delete_course(role, user, course): | |
46 | + if (role == SystemAdmin): | |
47 | + return True | |
48 | + | |
49 | + if (user in course.professors.all()): | |
50 | + return True | |
51 | + | |
52 | + return False | ... | ... |
courses/templates/course/create.html
... | ... | @@ -21,7 +21,7 @@ |
21 | 21 | <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput"> |
22 | 22 | <label for="{{ field.auto_id }}">{{ field.label }}</label> |
23 | 23 | {% if field.auto_id == 'id_init_register_date' or field.auto_id == 'id_end_register_date' or field.auto_id == 'id_init_date' or field.auto_id == 'id_end_date'%} |
24 | - {% render_field field class='form-control' type='date' %} | |
24 | + <input type="date" class="form-control"name="{{field.name}}" value="{% if field.value.year %}{{field.value|date:'Y-m-d'}}{% else %}{{field.value}}{% endif %}" min="{{now|date:'Y-m-d'}}"> | |
25 | 25 | {% elif field.auto_id == 'id_image' %} |
26 | 26 | {% render_field field class='form-control' %} |
27 | 27 | <div class="input-group"> | ... | ... |
courses/templates/course/delete.html
1 | -{% extends 'app/base.html' %} | |
1 | +{% extends 'course/view.html' %} | |
2 | 2 | |
3 | 3 | {% load static i18n %} |
4 | 4 | |
... | ... | @@ -9,23 +9,15 @@ |
9 | 9 | </ol> |
10 | 10 | {% endblock %} |
11 | 11 | |
12 | -{% block sidebar %} | |
13 | - <div class="list-group"> | |
14 | - <a href="{% url 'course:manage' %}" class="list-group-item"> | |
15 | - {% trans 'Courses' %} | |
16 | - </a> | |
17 | - <a href="{% url 'course:create' %}" class="list-group-item"> | |
18 | - {% trans 'Create Course' %} | |
19 | - </a> | |
20 | - </div> | |
21 | - | |
22 | -{% endblock %} | |
23 | - | |
24 | 12 | {% block content %} |
25 | - <form action="" method="post"> | |
26 | - {% csrf_token %} | |
27 | - <p>{% trans 'Are you sure you want to delete the couse' %} "{{ object }}"?</p> | |
28 | - <input type="submit" class="btn btn-success btn-sm" value="{% trans 'Yes' %}" /> | |
29 | - <a href="{% url 'course:manage' %}" class="btn btn-danger btn-sm">{% trans 'No' %}</a> | |
30 | - </form> | |
13 | +<div class="panel panel-default"> | |
14 | + <div class="panel-body"> | |
15 | + <form action="" method="post"> | |
16 | + {% csrf_token %} | |
17 | + <h2>{% trans 'Are you sure you want to delete the course' %} "{{course}}"?</h2> | |
18 | + <input type="submit" class="btn btn-raised btn-success btn-lg" value="{% trans 'Yes' %}" /> | |
19 | + <a href="{% url 'course:view' course.slug%}" class="btn btn-raised btn-danger btn-lg">{% trans 'No' %}</a> | |
20 | + </form> | |
21 | + </div> | |
22 | +</div> | |
31 | 23 | {% endblock %} | ... | ... |
courses/templates/course/index.html
... | ... | @@ -54,7 +54,11 @@ |
54 | 54 | {% for course in courses %} |
55 | 55 | <div class="row well well-inverse"> |
56 | 56 | <div class="col-md-2"> |
57 | + {% if course.image %} | |
57 | 58 | <img src="{{ course.image.url }}" class="img-responsive" /> |
59 | + {% else %} | |
60 | + <img src="" class="img-responsive" /> | |
61 | + {% endif %} | |
58 | 62 | </div> |
59 | 63 | <div class="col-md-10"> |
60 | 64 | <div class="row"> | ... | ... |
courses/templates/course/update.html
1 | -{% extends 'app/base.html' %} | |
1 | +{% extends 'course/view.html' %} | |
2 | 2 | |
3 | 3 | {% load static i18n %} |
4 | 4 | {% load widget_tweaks %} |
5 | 5 | |
6 | 6 | {% block breadcrumbs %} |
7 | 7 | <ol class="breadcrumb"> |
8 | - <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> | |
9 | - <li class="active">{% trans 'Edit Course' %}</li> | |
8 | + <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> | |
9 | + <li class="active">{% trans 'Edit Course' %}</li> | |
10 | 10 | </ol> |
11 | 11 | {% endblock %} |
12 | - | |
13 | -{% block sidebar %} | |
14 | - <div class="list-group"> | |
15 | - <a href="{% url 'course:manage' %}" class="list-group-item"> | |
16 | - {% trans 'Courses' %} | |
17 | - </a> | |
18 | - <a href="{% url 'course:manage_mods' course.slug %}" class="list-group-item"> | |
19 | - {% trans 'Manage Modules' %} | |
20 | - </a> | |
21 | - <a href="#" class="list-group-item"> | |
22 | - {% trans 'Participants' %} | |
23 | - </a> | |
24 | - </div> | |
25 | -{% endblock %} | |
26 | - | |
27 | 12 | {% block content %} |
28 | - <div class="alert alert-info alert-dismissible" role="alert"> | |
29 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
30 | - <span aria-hidden="true">×</span> | |
31 | - </button> | |
32 | - <p>{% trans 'All fields are required' %}</p> | |
33 | - </div> | |
34 | 13 | |
35 | - <form method="post" action="" enctype="multipart/form-data"> | |
36 | - {% csrf_token %} | |
37 | - {% for field in form %} | |
38 | - <div class="form-group{% if form.has_error %} has-error {% endif %}"> | |
39 | - <label for="{{ field.auto_id }}">{{ field.label }}</label> | |
40 | - {% render_field field class='form-control input-sm' %} | |
41 | - <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
42 | - {% if field.errors.length > 0 %} | |
43 | - <div class="alert alert-danger alert-dismissible" role="alert"> | |
44 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
45 | - <span aria-hidden="true">×</span> | |
46 | - </button> | |
47 | - <ul> | |
48 | - {% for error in field.errors %} | |
49 | - <li>{{ error }}</li> | |
50 | - {% endfor %} | |
51 | - </ul> | |
14 | +</br> | |
15 | +<div class="card card-content"> | |
16 | + <div class="card-body"> | |
17 | + <form method="post" action="" enctype="multipart/form-data"> | |
18 | + {% csrf_token %} | |
19 | + {% for field in form %} | |
20 | + <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput"> | |
21 | + <label for="{{ field.auto_id }}">{{ field.label }}</label> | |
22 | + {% if field.auto_id == 'id_init_register_date' or field.auto_id == 'id_end_register_date' or field.auto_id == 'id_init_date' or field.auto_id == 'id_end_date'%} | |
23 | + <input type="date" class="form-control"name="{{field.name}}" value="{% if field.value.year %}{{field.value|date:'Y-m-d'}}{% else %}{{field.value}}{% endif %}" min="{{now|date:'Y-m-d'}}"> | |
24 | + {% elif field.auto_id == 'id_image' %} | |
25 | + {% render_field field class='form-control' %} | |
26 | + <div class="input-group"> | |
27 | + <input type="text" readonly="" class="form-control" placeholder="Choose your photo..."/> | |
28 | + <span class="input-group-btn input-group-sm"> | |
29 | + <button type="button" class="btn btn-fab btn-fab-mini"> | |
30 | + <i class="material-icons">attach_file</i> | |
31 | + </button> | |
32 | + </span> | |
33 | + </div> | |
34 | + {% else %} | |
35 | + {% render_field field class='form-control' %} | |
36 | + {% endif %} | |
37 | + <span class="help-block">{{ field.help_text }}</span> | |
38 | + {% if field.errors %} | |
39 | + <div class="row"> | |
40 | + </br> | |
41 | + <div class="alert alert-danger alert-dismissible" role="alert"> | |
42 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
43 | + <span aria-hidden="true">×</span> | |
44 | + </button> | |
45 | + <ul> | |
46 | + {% for error in field.errors %} | |
47 | + <li>{{ error }}</li> | |
48 | + {% endfor %} | |
49 | + </ul> | |
50 | + </div> | |
52 | 51 | </div> |
52 | + {% endif %} | |
53 | 53 | </div> |
54 | - {% endif %} | |
54 | + {% endfor %} | |
55 | + <div class="row text-center"> | |
56 | + <input type="submit" value="{% trans 'Update' %}" class="btn btn-primary" /> | |
55 | 57 | </div> |
56 | - {% endfor %} | |
57 | - <input type="submit" value="{% trans 'Save' %}" class="btn btn-sm btn-success" /> | |
58 | - </form> | |
59 | - <br clear="all" /> | |
58 | + </form> | |
59 | + </div> | |
60 | +</div> | |
61 | +</br> | |
62 | +</br> | |
63 | +</br> | |
60 | 64 | {% endblock %} | ... | ... |
courses/templates/subject/delete.html
... | ... | @@ -8,7 +8,7 @@ |
8 | 8 | <div class="panel-body"> |
9 | 9 | <form action="" method="post"> |
10 | 10 | {% csrf_token %} |
11 | - <h2>{% trans 'Are you sure you want to delete the category' %} "{{subject}}"?</h2> | |
11 | + <h2>{% trans 'Are you sure you want to delete the subject' %} "{{subject}}"?</h2> | |
12 | 12 | <input type="submit" class="btn btn-raised btn-success btn-lg" value="{% trans 'Yes' %}" /> |
13 | 13 | <a href="{% url 'course:view_subject' subject.slug%}" class="btn btn-raised btn-danger btn-lg">{% trans 'No' %}</a> |
14 | 14 | </form> | ... | ... |
courses/urls.py
... | ... | @@ -5,9 +5,9 @@ from . import views |
5 | 5 | urlpatterns = [ |
6 | 6 | url(r'^$', views.IndexView.as_view(), name='manage'), |
7 | 7 | url(r'^create/$', views.CreateCourseView.as_view(), name='create'), |
8 | - url(r'^edit/(?P<slug>[\w_-]+)/$', views.UpdateView.as_view(), name='update'), | |
8 | + url(r'^edit/(?P<slug>[\w_-]+)/$', views.UpdateCourseView.as_view(), name='update'), | |
9 | 9 | url(r'^(?P<slug>[\w_-]+)/$', views.CourseView.as_view(), name='view'), |
10 | - url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteView.as_view(), name='delete'), | |
10 | + url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteCourseView.as_view(), name='delete'), | |
11 | 11 | url(r'^category/(?P<slug>[\w_-]+)/$', views.FilteredView.as_view(), name='filter'), |
12 | 12 | url(r'^categories/$', views.IndexCatView.as_view(), name='manage_cat'), |
13 | 13 | url(r'^categories/create/$', views.CreateCatView.as_view(), name="create_cat"), | ... | ... |
courses/views.py
... | ... | @@ -12,10 +12,11 @@ from rolepermissions.verifications import has_role |
12 | 12 | from django.db.models import Q |
13 | 13 | from rolepermissions.verifications import has_object_permission |
14 | 14 | |
15 | -from .forms import CourseForm, CategoryForm, SubjectForm,TopicForm | |
15 | +from .forms import CourseForm, UpdateCourseForm, CategoryForm, SubjectForm,TopicForm | |
16 | 16 | from .models import Course, Subject, Category,Topic |
17 | 17 | from core.mixins import NotificationMixin |
18 | 18 | |
19 | +from datetime import date | |
19 | 20 | |
20 | 21 | class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView): |
21 | 22 | |
... | ... | @@ -40,32 +41,86 @@ class CreateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,gener |
40 | 41 | template_name = 'course/create.html' |
41 | 42 | form_class = CourseForm |
42 | 43 | success_url = reverse_lazy('course:manage') |
44 | + | |
43 | 45 | def form_valid(self, form): |
44 | 46 | self.object = form.save() |
45 | 47 | self.object.professors.add(self.request.user) |
46 | 48 | return super(CreateCourseView, self).form_valid(form) |
47 | 49 | |
48 | -class UpdateView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): | |
50 | + def get_context_data(self, **kwargs): | |
51 | + context = super(CreateCourseView, self).get_context_data(**kwargs) | |
52 | + | |
53 | + if has_role(self.request.user,'system_admin'): | |
54 | + courses = Course.objects.all() | |
55 | + elif has_role(self.request.user,'professor'): | |
56 | + courses = self.request.user.courses.all() | |
57 | + context['courses'] = courses | |
58 | + context['title'] = _("Create Course") | |
59 | + context['now'] = date.today() | |
60 | + return context | |
61 | + | |
62 | +class UpdateCourseView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): | |
49 | 63 | |
50 | 64 | allowed_roles = ['professor', 'system_admin'] |
51 | 65 | login_url = reverse_lazy("core:home") |
52 | 66 | redirect_field_name = 'next' |
53 | 67 | template_name = 'course/update.html' |
54 | 68 | model = Course |
55 | - form_class = CourseForm | |
69 | + form_class = UpdateCourseForm | |
70 | + | |
71 | + def dispatch(self, *args, **kwargs): | |
72 | + course = get_object_or_404(Course, slug = self.kwargs.get('slug')) | |
73 | + if(not has_object_permission('update_course', self.request.user, course)): | |
74 | + return self.handle_no_permission() | |
75 | + return super(UpdateCourseView, self).dispatch(*args, **kwargs) | |
76 | + | |
77 | + def get_context_data(self, **kwargs): | |
78 | + context = super(UpdateCourseView, self).get_context_data(**kwargs) | |
79 | + course = get_object_or_404(Course, slug = self.kwargs.get('slug')) | |
80 | + | |
81 | + if has_role(self.request.user,'system_admin'): | |
82 | + courses = Course.objects.all() | |
83 | + elif has_role(self.request.user,'professor'): | |
84 | + courses = self.request.user.courses.all() | |
85 | + context['courses'] = courses | |
86 | + context['title'] = course.name | |
87 | + context['now'] = date.today() | |
88 | + return context | |
89 | + | |
90 | + def get_success_url(self): | |
91 | + return reverse_lazy('course:view', kwargs={'slug' : self.object.slug}) | |
92 | + | |
93 | + | |
94 | + | |
95 | +class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): | |
96 | + | |
97 | + allowed_roles = ['professor', 'system_admin'] | |
98 | + login_url = reverse_lazy("core:home") | |
99 | + redirect_field_name = 'next' | |
100 | + model = Course | |
101 | + template_name = 'course/delete.html' | |
56 | 102 | success_url = reverse_lazy('course:manage') |
57 | 103 | |
58 | - def form_valid(self, form): | |
59 | - self.object = form.save(commit = False) | |
60 | - self.object.slug = slugify(self.object.name) | |
61 | - self.object.save() | |
104 | + def dispatch(self, *args, **kwargs): | |
105 | + course = get_object_or_404(Course, slug = self.kwargs.get('slug')) | |
106 | + if(not has_object_permission('delete_course', self.request.user, course)): | |
107 | + return self.handle_no_permission() | |
108 | + return super(DeleteCourseView, self).dispatch(*args, **kwargs) | |
62 | 109 | |
63 | - return super(UpdateView, self).form_valid(form) | |
110 | + def get_context_data(self, **kwargs): | |
111 | + context = super(DeleteCourseView, self).get_context_data(**kwargs) | |
112 | + course = get_object_or_404(Course, slug = self.kwargs.get('slug')) | |
64 | 113 | |
65 | - def render_to_response(self, context, **response_kwargs): | |
66 | - messages.success(self.request, _('Course edited successfully!')) | |
114 | + if has_role(self.request.user,'system_admin'): | |
115 | + courses = Course.objects.all() | |
116 | + elif has_role(self.request.user,'professor'): | |
117 | + courses = self.request.user.courses.all() | |
118 | + context['courses'] = courses | |
119 | + print (courses,"jdhksjbjs") | |
120 | + context['title'] = course.name | |
121 | + | |
122 | + return context | |
67 | 123 | |
68 | - return self.response_class(request=self.request, template=self.get_template_names(), context=context, using=self.template_engine) | |
69 | 124 | |
70 | 125 | class CourseView(LoginRequiredMixin, NotificationMixin, generic.DetailView): |
71 | 126 | |
... | ... | @@ -375,4 +430,4 @@ class DeleteSubjectView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): |
375 | 430 | return context |
376 | 431 | |
377 | 432 | def get_success_url(self): |
378 | - return reverse_lazy('course:view_subject', kwargs={'slug' : self.object.course.subjects.all()[0].slug}) | |
433 | + return reverse_lazy('course:view', kwargs={'slug' : self.object.course.slug}) | ... | ... |