Commit 81b068e13e0a2b4e0cc7eb177dac337302233d82
1 parent
e484c624
Exists in
master
and in
3 other branches
creating subject functional and breadcrumbs ok
Showing
13 changed files
with
270 additions
and
17 deletions
Show diff stats
categories/forms.py
| ... | ... | @@ -6,7 +6,7 @@ class CategoryForm(forms.ModelForm): |
| 6 | 6 | model = Category |
| 7 | 7 | fields = ( 'name', 'description', 'visible', 'coordinators', ) |
| 8 | 8 | widgets = { |
| 9 | - 'description': forms.Textarea, | |
| 10 | - 'coordinators' : forms.SelectMultiple, | |
| 11 | - } | |
| 12 | - | |
| 13 | 9 | \ No newline at end of file |
| 10 | + 'description': forms.Textarea, | |
| 11 | + 'coordinators' : forms.SelectMultiple, | |
| 12 | + } | |
| 13 | + | |
| 14 | 14 | \ No newline at end of file | ... | ... |
categories/views.py
| ... | ... | @@ -128,7 +128,7 @@ class CreateCategory(views.SuperuserRequiredMixin, HasRoleMixin, LogMixin, Creat |
| 128 | 128 | return super(CreateCategory, self).form_valid(form) |
| 129 | 129 | |
| 130 | 130 | def get_success_url(self): |
| 131 | - print(self.object.coordinators) | |
| 131 | + | |
| 132 | 132 | objeto = self.object.name |
| 133 | 133 | messages.success(self.request, _('Category "%s" register successfully!')%(objeto)) |
| 134 | 134 | return reverse_lazy('categories:index') | ... | ... |
subjects/admin.py
| ... | ... | @@ -4,7 +4,7 @@ from .models import Subject, Marker |
| 4 | 4 | from .forms import CreateSubjectForm, CreateMarkerForm |
| 5 | 5 | |
| 6 | 6 | class SubjectAdmin(admin.ModelAdmin): |
| 7 | - list_display = ['name', 'description_brief', 'description', 'init_date', 'end_date', 'visible', 'professor',] | |
| 7 | + list_display = ['name', 'description_brief', 'description', 'init_date', 'end_date', 'visible',] | |
| 8 | 8 | search_fields = ['name'] |
| 9 | 9 | form = CreateSubjectForm |
| 10 | 10 | ... | ... |
subjects/forms.py
| ... | ... | @@ -2,10 +2,17 @@ from .models import Subject, Marker |
| 2 | 2 | from django import forms |
| 3 | 3 | class CreateSubjectForm(forms.ModelForm): |
| 4 | 4 | # TODO: Define form fields here |
| 5 | - model = Subject | |
| 5 | + class Meta: | |
| 6 | + model = Subject | |
| 7 | + | |
| 8 | + fields = ('name', 'description_brief', 'description', 'markers', 'init_date', 'end_date', 'visible', 'professor', | |
| 9 | + 'students', ) | |
| 10 | + | |
| 11 | + widgets = { | |
| 12 | + 'professor': forms.SelectMultiple, | |
| 13 | + 'students': forms.SelectMultiple, | |
| 14 | + } | |
| 6 | 15 | |
| 7 | - fields = ('name', 'description_brief', 'description', 'init_date', 'end_date', 'visible', 'markers', 'professor', | |
| 8 | - 'students', 'category', ) | |
| 9 | 16 | |
| 10 | 17 | |
| 11 | 18 | class CreateMarkerForm(forms.ModelForm): | ... | ... |
| ... | ... | @@ -0,0 +1,42 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2017-01-02 20:27 | |
| 3 | +from __future__ import unicode_literals | |
| 4 | + | |
| 5 | +from django.conf import settings | |
| 6 | +from django.db import migrations, models | |
| 7 | +import django.db.models.deletion | |
| 8 | + | |
| 9 | + | |
| 10 | +class Migration(migrations.Migration): | |
| 11 | + | |
| 12 | + dependencies = [ | |
| 13 | + ('subjects', '0002_auto_20161226_2054'), | |
| 14 | + ] | |
| 15 | + | |
| 16 | + operations = [ | |
| 17 | + migrations.AlterField( | |
| 18 | + model_name='subject', | |
| 19 | + name='description', | |
| 20 | + field=models.CharField(blank=True, max_length=300, verbose_name='description'), | |
| 21 | + ), | |
| 22 | + migrations.AlterField( | |
| 23 | + model_name='subject', | |
| 24 | + name='description_brief', | |
| 25 | + field=models.CharField(blank=True, max_length=100, verbose_name='simpler_description'), | |
| 26 | + ), | |
| 27 | + migrations.AlterField( | |
| 28 | + model_name='subject', | |
| 29 | + name='markers', | |
| 30 | + field=models.ManyToManyField(blank=True, null=True, to='subjects.Marker', verbose_name='markers'), | |
| 31 | + ), | |
| 32 | + migrations.AlterField( | |
| 33 | + model_name='subject', | |
| 34 | + name='max_upload_size', | |
| 35 | + field=models.IntegerField(default=1024, null=True, verbose_name='Maximum upload size'), | |
| 36 | + ), | |
| 37 | + migrations.AlterField( | |
| 38 | + model_name='subject', | |
| 39 | + name='professor', | |
| 40 | + field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='professor', to=settings.AUTH_USER_MODEL), | |
| 41 | + ), | |
| 42 | + ] | ... | ... |
| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2017-01-02 20:37 | |
| 3 | +from __future__ import unicode_literals | |
| 4 | + | |
| 5 | +from django.db import migrations, models | |
| 6 | +import django.db.models.deletion | |
| 7 | + | |
| 8 | + | |
| 9 | +class Migration(migrations.Migration): | |
| 10 | + | |
| 11 | + dependencies = [ | |
| 12 | + ('subjects', '0003_auto_20170102_1727'), | |
| 13 | + ] | |
| 14 | + | |
| 15 | + operations = [ | |
| 16 | + migrations.AlterField( | |
| 17 | + model_name='subject', | |
| 18 | + name='category', | |
| 19 | + field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='subject_category', to='categories.Category'), | |
| 20 | + ), | |
| 21 | + ] | ... | ... |
| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2017-01-02 20:37 | |
| 3 | +from __future__ import unicode_literals | |
| 4 | + | |
| 5 | +from django.db import migrations, models | |
| 6 | +import django.db.models.deletion | |
| 7 | + | |
| 8 | + | |
| 9 | +class Migration(migrations.Migration): | |
| 10 | + | |
| 11 | + dependencies = [ | |
| 12 | + ('subjects', '0004_auto_20170102_1737'), | |
| 13 | + ] | |
| 14 | + | |
| 15 | + operations = [ | |
| 16 | + migrations.AlterField( | |
| 17 | + model_name='subject', | |
| 18 | + name='category', | |
| 19 | + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subject_category', to='categories.Category'), | |
| 20 | + ), | |
| 21 | + ] | ... | ... |
| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2017-01-02 20:39 | |
| 3 | +from __future__ import unicode_literals | |
| 4 | + | |
| 5 | +from django.conf import settings | |
| 6 | +from django.db import migrations, models | |
| 7 | + | |
| 8 | + | |
| 9 | +class Migration(migrations.Migration): | |
| 10 | + | |
| 11 | + dependencies = [ | |
| 12 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 13 | + ('subjects', '0005_auto_20170102_1737'), | |
| 14 | + ] | |
| 15 | + | |
| 16 | + operations = [ | |
| 17 | + migrations.RemoveField( | |
| 18 | + model_name='subject', | |
| 19 | + name='professor', | |
| 20 | + ), | |
| 21 | + migrations.AddField( | |
| 22 | + model_name='subject', | |
| 23 | + name='professor', | |
| 24 | + field=models.ManyToManyField(blank=True, related_name='professor', to=settings.AUTH_USER_MODEL), | |
| 25 | + ), | |
| 26 | + ] | ... | ... |
subjects/models.py
| ... | ... | @@ -18,24 +18,24 @@ class Subject(models.Model): |
| 18 | 18 | name = models.CharField( _("Name"), unique = True,max_length= 200) |
| 19 | 19 | slug = AutoSlugField(_("Slug"),populate_from='name',unique=True) |
| 20 | 20 | |
| 21 | - description_brief = models.CharField(_("simpler_description"), max_length= 100) | |
| 22 | - description = models.CharField(_("description"), max_length = 300) | |
| 21 | + description_brief = models.CharField(_("simpler_description"), max_length= 100, blank=True) | |
| 22 | + description = models.CharField(_("description"), max_length = 300, blank= True) | |
| 23 | 23 | visible = models.BooleanField(_("visible")) |
| 24 | 24 | |
| 25 | 25 | init_date = models.DateField(_('Begin of Subject Date')) |
| 26 | 26 | end_date = models.DateField(_('End of Subject Date')) |
| 27 | 27 | |
| 28 | - markers = models.ManyToManyField(Marker, verbose_name='markers') | |
| 28 | + markers = models.ManyToManyField(Marker, verbose_name='markers', blank=True, null=True) | |
| 29 | 29 | |
| 30 | 30 | create_date = models.DateTimeField(_('Creation Date'), auto_now_add = True) |
| 31 | 31 | update_date = models.DateTimeField(_('Date of last update'), auto_now=True) |
| 32 | 32 | |
| 33 | - professor = models.ForeignKey(User, related_name="professor") | |
| 33 | + professor = models.ManyToManyField(User, related_name="professor", blank=True) | |
| 34 | 34 | students = models.ManyToManyField(User,verbose_name=_('Students'), related_name='subject_student', blank = True) |
| 35 | 35 | |
| 36 | - category = models.ForeignKey(Category, related_name="subject_category") | |
| 36 | + category = models.ForeignKey(Category, related_name="subject_category", null=True) | |
| 37 | 37 | |
| 38 | - max_upload_size = models.IntegerField(_("Maximum upload size")) | |
| 38 | + max_upload_size = models.IntegerField(_("Maximum upload size"), default=1024, null=True) | |
| 39 | 39 | class Meta: |
| 40 | 40 | verbose_name = "Subject" |
| 41 | 41 | verbose_name_plural = "Subjects" | ... | ... |
| ... | ... | @@ -0,0 +1,94 @@ |
| 1 | +{% extends 'categories/create.html' %} | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | +{% load widget_tweaks static i18n permission_tags django_bootstrap_breadcrumbs switchevenodd %} | |
| 6 | + | |
| 7 | + | |
| 8 | +{% block breadcrumbs %} | |
| 9 | + {% clear_breadcrumbs %} | |
| 10 | + {% breadcrumb 'Home' 'categories:index' %} | |
| 11 | + | |
| 12 | + {% breadcrumb slug 'categories:index' %} | |
| 13 | + {% breadcrumb 'Create Subject' 'subjects:create' %} | |
| 14 | +{% endblock %} | |
| 15 | + | |
| 16 | +{% block content %} | |
| 17 | + {{ block.super }} | |
| 18 | + | |
| 19 | + | |
| 20 | + <script type="text/javascript"> | |
| 21 | + $('#id_professor').multiSelect({ | |
| 22 | + selectableHeader: "<input type='text' class='search-input category-search-users' autocomplete='off' placeholder=' '>", | |
| 23 | + selectionHeader: "<input type='text' class='search-input category-search-users' autocomplete='off' placeholder=''>", | |
| 24 | + afterInit: function(ms){ | |
| 25 | + var that = this, | |
| 26 | + $selectableSearch = that.$selectableUl.prev(), | |
| 27 | + $selectionSearch = that.$selectionUl.prev(), | |
| 28 | + selectableSearchString = '#'+that.$container.attr('id')+' .ms-elem-selectable:not(.ms-selected)', | |
| 29 | + selectionSearchString = '#'+that.$container.attr('id')+' .ms-elem-selection.ms-selected'; | |
| 30 | + | |
| 31 | + that.qs1 = $selectableSearch.quicksearch(selectableSearchString) | |
| 32 | + .on('keydown', function(e){ | |
| 33 | + if (e.which === 40){ | |
| 34 | + that.$selectableUl.focus(); | |
| 35 | + return false; | |
| 36 | + } | |
| 37 | + }); | |
| 38 | + | |
| 39 | + that.qs2 = $selectionSearch.quicksearch(selectionSearchString) | |
| 40 | + .on('keydown', function(e){ | |
| 41 | + if (e.which == 40){ | |
| 42 | + that.$selectionUl.focus(); | |
| 43 | + return false; | |
| 44 | + } | |
| 45 | + }); | |
| 46 | + }, | |
| 47 | + afterSelect: function(){ | |
| 48 | + this.qs1.cache(); | |
| 49 | + this.qs2.cache(); | |
| 50 | + }, | |
| 51 | + afterDeselect: function(){ | |
| 52 | + this.qs1.cache(); | |
| 53 | + this.qs2.cache(); | |
| 54 | + } | |
| 55 | + });// Used to create multi-select css style | |
| 56 | + | |
| 57 | + $('#id_students').multiSelect({ | |
| 58 | + selectableHeader: "<input type='text' class='search-input category-search-users' autocomplete='off' placeholder=' '>", | |
| 59 | + selectionHeader: "<input type='text' class='search-input category-search-users' autocomplete='off' placeholder=''>", | |
| 60 | + afterInit: function(ms){ | |
| 61 | + var that = this, | |
| 62 | + $selectableSearch = that.$selectableUl.prev(), | |
| 63 | + $selectionSearch = that.$selectionUl.prev(), | |
| 64 | + selectableSearchString = '#'+that.$container.attr('id')+' .ms-elem-selectable:not(.ms-selected)', | |
| 65 | + selectionSearchString = '#'+that.$container.attr('id')+' .ms-elem-selection.ms-selected'; | |
| 66 | + | |
| 67 | + that.qs1 = $selectableSearch.quicksearch(selectableSearchString) | |
| 68 | + .on('keydown', function(e){ | |
| 69 | + if (e.which === 40){ | |
| 70 | + that.$selectableUl.focus(); | |
| 71 | + return false; | |
| 72 | + } | |
| 73 | + }); | |
| 74 | + | |
| 75 | + that.qs2 = $selectionSearch.quicksearch(selectionSearchString) | |
| 76 | + .on('keydown', function(e){ | |
| 77 | + if (e.which == 40){ | |
| 78 | + that.$selectionUl.focus(); | |
| 79 | + return false; | |
| 80 | + } | |
| 81 | + }); | |
| 82 | + }, | |
| 83 | + afterSelect: function(){ | |
| 84 | + this.qs1.cache(); | |
| 85 | + this.qs2.cache(); | |
| 86 | + }, | |
| 87 | + afterDeselect: function(){ | |
| 88 | + this.qs1.cache(); | |
| 89 | + this.qs2.cache(); | |
| 90 | + } | |
| 91 | + });// Used to create multi-select css style | |
| 92 | + </script> | |
| 93 | +{% endblock content %} | |
| 94 | + | ... | ... |
subjects/templates/subjects/list.html
| ... | ... | @@ -86,7 +86,7 @@ |
| 86 | 86 | |
| 87 | 87 | {{category.description|safe}} |
| 88 | 88 | {% if user in category.coordinators.all %} |
| 89 | - <button class="create-subject-btn"> {% trans "create new subject" %} </button> | |
| 89 | + <a href="{% url 'subjects:create' category.slug %}"><button class="create-subject-btn"> {% trans "create new subject" %} </button></a> | |
| 90 | 90 | {% endif %} |
| 91 | 91 | |
| 92 | 92 | </div> | ... | ... |
subjects/urls.py
subjects/views.py
| ... | ... | @@ -23,6 +23,7 @@ from log.models import Log |
| 23 | 23 | |
| 24 | 24 | import time |
| 25 | 25 | |
| 26 | +from .forms import CreateSubjectForm | |
| 26 | 27 | from users.models import User |
| 27 | 28 | |
| 28 | 29 | |
| ... | ... | @@ -57,9 +58,49 @@ class IndexView(LoginRequiredMixin, ListView): |
| 57 | 58 | |
| 58 | 59 | def get_context_data(self, **kwargs): |
| 59 | 60 | context = super(IndexView, self).get_context_data(**kwargs) |
| 60 | - categories = self.get_queryset().order_by('name') | |
| 61 | + if self.request.user.is_staff: | |
| 62 | + categories = self.get_queryset().order_by('name') | |
| 63 | + else: | |
| 64 | + categories = self.get_queryset().order_by('name').filter(visible=True) | |
| 61 | 65 | |
| 62 | 66 | |
| 63 | 67 | context['categories'] = categories |
| 64 | 68 | |
| 65 | 69 | return context |
| 70 | + | |
| 71 | +class SubjectCreateView(CreateView): | |
| 72 | + model = Subject | |
| 73 | + template_name = "subjects/create.html" | |
| 74 | + | |
| 75 | + login_url = reverse_lazy('users:login') | |
| 76 | + form_class = CreateSubjectForm | |
| 77 | + | |
| 78 | + success_url = reverse_lazy('subject:index') | |
| 79 | + | |
| 80 | + def get_initial(self): | |
| 81 | + initial = super(SubjectCreateView, self).get_initial() | |
| 82 | + initial['category'] = Category.objects.all().filter(slug=self.kwargs['slug']) | |
| 83 | + | |
| 84 | + return initial | |
| 85 | + | |
| 86 | + def get_context_data(self, **kwargs): | |
| 87 | + context = super(SubjectCreateView, self).get_context_data(**kwargs) | |
| 88 | + context['slug'] = self.kwargs['slug'] | |
| 89 | + return context | |
| 90 | + def form_valid(self, form): | |
| 91 | + | |
| 92 | + self.object = form.save() | |
| 93 | + self.object.category = Category.objects.get(slug=self.kwargs['slug']) | |
| 94 | + self.object.save() | |
| 95 | + | |
| 96 | + | |
| 97 | + return super(SubjectCreateView, self).form_valid(form) | |
| 98 | + | |
| 99 | + def get_success_url(self): | |
| 100 | + | |
| 101 | + | |
| 102 | + objeto = self.object.name | |
| 103 | + messages.success(self.request, _('Subject "%s" registered successfully!')%(objeto)) | |
| 104 | + return reverse_lazy('subjects:index') | |
| 105 | + | |
| 106 | + | ... | ... |