Commit 4eb261b5eceaaef2c9e6ff9c264bad94021fb23d
1 parent
e753a300
Exists in
master
and in
5 other branches
create, update and delete exercise (views, urls, templates)
Showing
43 changed files
with
900 additions
and
317 deletions
Show diff stats
amadeus/settings.py
app/migrations/0001_initial.py
core/migrations/0001_initial.py
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | -# Generated by Django 1.10 on 2016-11-13 17:47 | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 3 | 3 | from __future__ import unicode_literals |
| 4 | 4 | |
| 5 | 5 | import autoslug.fields |
| 6 | -from django.conf import settings | |
| 7 | 6 | import django.contrib.postgres.fields.jsonb |
| 8 | 7 | from django.db import migrations, models |
| 9 | 8 | import django.db.models.deletion |
| ... | ... | @@ -14,7 +13,6 @@ class Migration(migrations.Migration): |
| 14 | 13 | initial = True |
| 15 | 14 | |
| 16 | 15 | dependencies = [ |
| 17 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 18 | 16 | ] |
| 19 | 17 | |
| 20 | 18 | operations = [ |
| ... | ... | @@ -35,7 +33,6 @@ class Migration(migrations.Migration): |
| 35 | 33 | name='Action_Resource', |
| 36 | 34 | fields=[ |
| 37 | 35 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
| 38 | - ('action', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action', verbose_name='Action_Applied')), | |
| 39 | 36 | ], |
| 40 | 37 | options={ |
| 41 | 38 | 'verbose_name': 'Action_Resource', |
| ... | ... | @@ -49,8 +46,6 @@ class Migration(migrations.Migration): |
| 49 | 46 | ('component', models.TextField(verbose_name='Component (Module / App)')), |
| 50 | 47 | ('context', django.contrib.postgres.fields.jsonb.JSONField(blank=True, verbose_name='Context')), |
| 51 | 48 | ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')), |
| 52 | - ('action_resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource')), | |
| 53 | - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Actor')), | |
| 54 | 49 | ], |
| 55 | 50 | options={ |
| 56 | 51 | 'verbose_name': 'Log', |
| ... | ... | @@ -77,8 +72,6 @@ class Migration(migrations.Migration): |
| 77 | 72 | ('read', models.BooleanField(default=False, verbose_name='Read')), |
| 78 | 73 | ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')), |
| 79 | 74 | ('action_resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource')), |
| 80 | - ('actor', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notification_Performer', to=settings.AUTH_USER_MODEL, verbose_name='Perfomer')), | |
| 81 | - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notification_Actor', to=settings.AUTH_USER_MODEL, verbose_name='User')), | |
| 82 | 75 | ], |
| 83 | 76 | options={ |
| 84 | 77 | 'verbose_name': 'Notification', |
| ... | ... | @@ -99,9 +92,4 @@ class Migration(migrations.Migration): |
| 99 | 92 | 'verbose_name_plural': 'Resources', |
| 100 | 93 | }, |
| 101 | 94 | ), |
| 102 | - migrations.AddField( | |
| 103 | - model_name='action_resource', | |
| 104 | - name='resource', | |
| 105 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Resource', verbose_name='Resource'), | |
| 106 | - ), | |
| 107 | 95 | ] | ... | ... |
| ... | ... | @@ -0,0 +1,50 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 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 | + initial = True | |
| 13 | + | |
| 14 | + dependencies = [ | |
| 15 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 16 | + ('core', '0001_initial'), | |
| 17 | + ] | |
| 18 | + | |
| 19 | + operations = [ | |
| 20 | + migrations.AddField( | |
| 21 | + model_name='notification', | |
| 22 | + name='actor', | |
| 23 | + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notification_Performer', to=settings.AUTH_USER_MODEL, verbose_name='Perfomer'), | |
| 24 | + ), | |
| 25 | + migrations.AddField( | |
| 26 | + model_name='notification', | |
| 27 | + name='user', | |
| 28 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notification_Actor', to=settings.AUTH_USER_MODEL, verbose_name='User'), | |
| 29 | + ), | |
| 30 | + migrations.AddField( | |
| 31 | + model_name='log', | |
| 32 | + name='action_resource', | |
| 33 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource'), | |
| 34 | + ), | |
| 35 | + migrations.AddField( | |
| 36 | + model_name='log', | |
| 37 | + name='user', | |
| 38 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Actor'), | |
| 39 | + ), | |
| 40 | + migrations.AddField( | |
| 41 | + model_name='action_resource', | |
| 42 | + name='action', | |
| 43 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action', verbose_name='Action_Applied'), | |
| 44 | + ), | |
| 45 | + migrations.AddField( | |
| 46 | + model_name='action_resource', | |
| 47 | + name='resource', | |
| 48 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Resource', verbose_name='Resource'), | |
| 49 | + ), | |
| 50 | + ] | ... | ... |
courses/admin.py
| 1 | 1 | from django.contrib import admin |
| 2 | 2 | |
| 3 | -from .models import CourseCategory, Course, Subject, Topic, Activity, Material, CategorySubject, Exercise | |
| 3 | +from .models import CourseCategory, Course, Subject, Topic, Activity, Material, CategorySubject | |
| 4 | 4 | |
| 5 | 5 | class CategoryAdmin(admin.ModelAdmin): |
| 6 | 6 | list_display = ['name', 'slug'] |
| ... | ... | @@ -30,15 +30,10 @@ class MaterialAdmin(admin.ModelAdmin): |
| 30 | 30 | list_display = ['name', 'slug'] |
| 31 | 31 | search_fields = ['name', 'slug'] |
| 32 | 32 | |
| 33 | -class ExerciseAdmin(admin.ModelAdmin): | |
| 34 | - list_display = ['name'] | |
| 35 | - search_fields = ['name'] | |
| 36 | - | |
| 37 | 33 | admin.site.register(CourseCategory, CategoryAdmin) |
| 38 | 34 | admin.site.register(Course, CourseAdmin) |
| 39 | 35 | admin.site.register(Subject, SubjectAdmin) |
| 40 | 36 | admin.site.register(Topic, TopicAdmin) |
| 41 | 37 | admin.site.register(Activity, ActivityAdmin) |
| 42 | 38 | admin.site.register(Material, MaterialAdmin) |
| 43 | -admin.site.register(Exercise, ExerciseAdmin) | |
| 44 | 39 | admin.site.register(CategorySubject, CategorySubjectAdmin) | ... | ... |
courses/migrations/0001_initial.py
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | -# Generated by Django 1.10 on 2016-11-13 17:47 | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 3 | 3 | from __future__ import unicode_literals |
| 4 | 4 | |
| 5 | 5 | import autoslug.fields |
| 6 | -from django.conf import settings | |
| 7 | 6 | from django.db import migrations, models |
| 8 | 7 | import django.db.models.deletion |
| 9 | 8 | import s3direct.fields |
| ... | ... | @@ -15,7 +14,6 @@ class Migration(migrations.Migration): |
| 15 | 14 | |
| 16 | 15 | dependencies = [ |
| 17 | 16 | ('core', '0001_initial'), |
| 18 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 19 | 17 | ] |
| 20 | 18 | |
| 21 | 19 | operations = [ |
| ... | ... | @@ -25,7 +23,6 @@ class Migration(migrations.Migration): |
| 25 | 23 | ('resource_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.Resource')), |
| 26 | 24 | ('limit_date', models.DateField(verbose_name='Deliver Date')), |
| 27 | 25 | ('all_students', models.BooleanField(default=False, verbose_name='All Students')), |
| 28 | - ('students', models.ManyToManyField(related_name='activities', to=settings.AUTH_USER_MODEL, verbose_name='Students')), | |
| 29 | 26 | ], |
| 30 | 27 | bases=('core.resource',), |
| 31 | 28 | ), |
| ... | ... | @@ -35,7 +32,6 @@ class Migration(migrations.Migration): |
| 35 | 32 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
| 36 | 33 | ('pdf', s3direct.fields.S3DirectField()), |
| 37 | 34 | ('name', models.CharField(max_length=100)), |
| 38 | - ('diet', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='courses.Activity')), | |
| 39 | 35 | ], |
| 40 | 36 | options={ |
| 41 | 37 | 'verbose_name': 'Activity File', |
| ... | ... | @@ -72,9 +68,9 @@ class Migration(migrations.Migration): |
| 72 | 68 | ('public', models.BooleanField(default=False, verbose_name='Public')), |
| 73 | 69 | ], |
| 74 | 70 | options={ |
| 71 | + 'ordering': ('create_date', 'name'), | |
| 75 | 72 | 'verbose_name': 'Course', |
| 76 | 73 | 'verbose_name_plural': 'Courses', |
| 77 | - 'ordering': ('create_date', 'name'), | |
| 78 | 74 | }, |
| 79 | 75 | ), |
| 80 | 76 | migrations.CreateModel( |
| ... | ... | @@ -112,7 +108,6 @@ class Migration(migrations.Migration): |
| 112 | 108 | fields=[ |
| 113 | 109 | ('resource_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.Resource')), |
| 114 | 110 | ('all_students', models.BooleanField(default=False, verbose_name='All Students')), |
| 115 | - ('students', models.ManyToManyField(related_name='materials', to=settings.AUTH_USER_MODEL, verbose_name='Students')), | |
| 116 | 111 | ], |
| 117 | 112 | bases=('core.resource',), |
| 118 | 113 | ), |
| ... | ... | @@ -128,15 +123,11 @@ class Migration(migrations.Migration): |
| 128 | 123 | ('end_date', models.DateField(verbose_name='End of Subject Date')), |
| 129 | 124 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), |
| 130 | 125 | ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), |
| 131 | - ('category', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subject_category', to='courses.CategorySubject', verbose_name='Category')), | |
| 132 | - ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subjects', to='courses.Course', verbose_name='Course')), | |
| 133 | - ('professors', models.ManyToManyField(related_name='professors_subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors')), | |
| 134 | - ('students', models.ManyToManyField(blank=True, related_name='subject_student', to=settings.AUTH_USER_MODEL, verbose_name='Students')), | |
| 135 | 126 | ], |
| 136 | 127 | options={ |
| 128 | + 'ordering': ('create_date', 'name'), | |
| 137 | 129 | 'verbose_name': 'Subject', |
| 138 | 130 | 'verbose_name_plural': 'Subjects', |
| 139 | - 'ordering': ('create_date', 'name'), | |
| 140 | 131 | }, |
| 141 | 132 | ), |
| 142 | 133 | migrations.CreateModel( |
| ... | ... | @@ -146,7 +137,6 @@ class Migration(migrations.Migration): |
| 146 | 137 | ('name', models.CharField(max_length=100, verbose_name='Name')), |
| 147 | 138 | ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True, verbose_name='Slug')), |
| 148 | 139 | ('description', models.TextField(blank=True, verbose_name='Description')), |
| 149 | - ('subjects', models.ManyToManyField(to='courses.Subject')), | |
| 150 | 140 | ], |
| 151 | 141 | options={ |
| 152 | 142 | 'verbose_name': 'subject category', |
| ... | ... | @@ -163,53 +153,11 @@ class Migration(migrations.Migration): |
| 163 | 153 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), |
| 164 | 154 | ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), |
| 165 | 155 | ('visible', models.BooleanField(default=False, verbose_name='Visible')), |
| 166 | - ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Owner')), | |
| 167 | - ('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Subject', verbose_name='Subject')), | |
| 168 | 156 | ], |
| 169 | 157 | options={ |
| 158 | + 'ordering': ('create_date', 'name'), | |
| 170 | 159 | 'verbose_name': 'Topic', |
| 171 | 160 | 'verbose_name_plural': 'Topics', |
| 172 | - 'ordering': ('create_date', 'name'), | |
| 173 | 161 | }, |
| 174 | 162 | ), |
| 175 | - migrations.AddField( | |
| 176 | - model_name='material', | |
| 177 | - name='topic', | |
| 178 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='courses.Topic', verbose_name='Topic'), | |
| 179 | - ), | |
| 180 | - migrations.AddField( | |
| 181 | - model_name='linkmaterial', | |
| 182 | - name='material', | |
| 183 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_link', to='courses.Material', verbose_name='Material'), | |
| 184 | - ), | |
| 185 | - migrations.AddField( | |
| 186 | - model_name='filematerial', | |
| 187 | - name='material', | |
| 188 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_file', to='courses.Material', verbose_name='Material'), | |
| 189 | - ), | |
| 190 | - migrations.AddField( | |
| 191 | - model_name='course', | |
| 192 | - name='category', | |
| 193 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='course_category', to='courses.CourseCategory', verbose_name='Category'), | |
| 194 | - ), | |
| 195 | - migrations.AddField( | |
| 196 | - model_name='course', | |
| 197 | - name='coordenator', | |
| 198 | - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='course_coordenator', to=settings.AUTH_USER_MODEL, verbose_name='Coordenator'), | |
| 199 | - ), | |
| 200 | - migrations.AddField( | |
| 201 | - model_name='course', | |
| 202 | - name='professors', | |
| 203 | - field=models.ManyToManyField(related_name='courses_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors'), | |
| 204 | - ), | |
| 205 | - migrations.AddField( | |
| 206 | - model_name='course', | |
| 207 | - name='students', | |
| 208 | - field=models.ManyToManyField(blank=True, related_name='courses_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
| 209 | - ), | |
| 210 | - migrations.AddField( | |
| 211 | - model_name='activity', | |
| 212 | - name='topic', | |
| 213 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='courses.Topic', verbose_name='Topic'), | |
| 214 | - ), | |
| 215 | 163 | ] | ... | ... |
| ... | ... | @@ -0,0 +1,110 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 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 | + initial = True | |
| 13 | + | |
| 14 | + dependencies = [ | |
| 15 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 16 | + ('courses', '0001_initial'), | |
| 17 | + ] | |
| 18 | + | |
| 19 | + operations = [ | |
| 20 | + migrations.AddField( | |
| 21 | + model_name='topic', | |
| 22 | + name='owner', | |
| 23 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Owner'), | |
| 24 | + ), | |
| 25 | + migrations.AddField( | |
| 26 | + model_name='topic', | |
| 27 | + name='subject', | |
| 28 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Subject', verbose_name='Subject'), | |
| 29 | + ), | |
| 30 | + migrations.AddField( | |
| 31 | + model_name='subjectcategory', | |
| 32 | + name='subjects', | |
| 33 | + field=models.ManyToManyField(to='courses.Subject'), | |
| 34 | + ), | |
| 35 | + migrations.AddField( | |
| 36 | + model_name='subject', | |
| 37 | + name='category', | |
| 38 | + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subject_category', to='courses.CategorySubject', verbose_name='Category'), | |
| 39 | + ), | |
| 40 | + migrations.AddField( | |
| 41 | + model_name='subject', | |
| 42 | + name='course', | |
| 43 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subjects', to='courses.Course', verbose_name='Course'), | |
| 44 | + ), | |
| 45 | + migrations.AddField( | |
| 46 | + model_name='subject', | |
| 47 | + name='professors', | |
| 48 | + field=models.ManyToManyField(related_name='professors_subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors'), | |
| 49 | + ), | |
| 50 | + migrations.AddField( | |
| 51 | + model_name='subject', | |
| 52 | + name='students', | |
| 53 | + field=models.ManyToManyField(blank=True, related_name='subject_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
| 54 | + ), | |
| 55 | + migrations.AddField( | |
| 56 | + model_name='material', | |
| 57 | + name='students', | |
| 58 | + field=models.ManyToManyField(related_name='materials', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
| 59 | + ), | |
| 60 | + migrations.AddField( | |
| 61 | + model_name='material', | |
| 62 | + name='topic', | |
| 63 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='courses.Topic', verbose_name='Topic'), | |
| 64 | + ), | |
| 65 | + migrations.AddField( | |
| 66 | + model_name='linkmaterial', | |
| 67 | + name='material', | |
| 68 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_link', to='courses.Material', verbose_name='Material'), | |
| 69 | + ), | |
| 70 | + migrations.AddField( | |
| 71 | + model_name='filematerial', | |
| 72 | + name='material', | |
| 73 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_file', to='courses.Material', verbose_name='Material'), | |
| 74 | + ), | |
| 75 | + migrations.AddField( | |
| 76 | + model_name='course', | |
| 77 | + name='category', | |
| 78 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='course_category', to='courses.CourseCategory', verbose_name='Category'), | |
| 79 | + ), | |
| 80 | + migrations.AddField( | |
| 81 | + model_name='course', | |
| 82 | + name='coordenator', | |
| 83 | + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='course_coordenator', to=settings.AUTH_USER_MODEL, verbose_name='Coordenator'), | |
| 84 | + ), | |
| 85 | + migrations.AddField( | |
| 86 | + model_name='course', | |
| 87 | + name='professors', | |
| 88 | + field=models.ManyToManyField(related_name='courses_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors'), | |
| 89 | + ), | |
| 90 | + migrations.AddField( | |
| 91 | + model_name='course', | |
| 92 | + name='students', | |
| 93 | + field=models.ManyToManyField(blank=True, related_name='courses_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
| 94 | + ), | |
| 95 | + migrations.AddField( | |
| 96 | + model_name='activityfile', | |
| 97 | + name='diet', | |
| 98 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='courses.Activity'), | |
| 99 | + ), | |
| 100 | + migrations.AddField( | |
| 101 | + model_name='activity', | |
| 102 | + name='students', | |
| 103 | + field=models.ManyToManyField(related_name='activities', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
| 104 | + ), | |
| 105 | + migrations.AddField( | |
| 106 | + model_name='activity', | |
| 107 | + name='topic', | |
| 108 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='courses.Topic', verbose_name='Topic'), | |
| 109 | + ), | |
| 110 | + ] | ... | ... |
courses/migrations/0002_exercise.py
| ... | ... | @@ -1,25 +0,0 @@ |
| 1 | -# -*- coding: utf-8 -*- | |
| 2 | -# Generated by Django 1.10 on 2016-11-13 19:30 | |
| 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 | - ('courses', '0001_initial'), | |
| 13 | - ] | |
| 14 | - | |
| 15 | - operations = [ | |
| 16 | - migrations.CreateModel( | |
| 17 | - name='Exercise', | |
| 18 | - fields=[ | |
| 19 | - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
| 20 | - ('file', models.FileField(upload_to='uploads/%Y/%m/%d')), | |
| 21 | - ('name', models.CharField(max_length=100)), | |
| 22 | - ('exercise', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_exercise', to='courses.Material', verbose_name='Material')), | |
| 23 | - ], | |
| 24 | - ), | |
| 25 | - ] |
courses/models.py
| ... | ... | @@ -157,14 +157,6 @@ class LinkMaterial(models.Model): |
| 157 | 157 | name = models.CharField(max_length=100) |
| 158 | 158 | description = models.TextField() |
| 159 | 159 | url = models.URLField('Link', max_length=300) |
| 160 | -""" | |
| 161 | -It represents the Exercises inside topic. | |
| 162 | -""" | |
| 163 | - | |
| 164 | -class Exercise(models.Model): | |
| 165 | - exercise = models.ForeignKey(Material, verbose_name = _('Material'), related_name='material_exercise') | |
| 166 | - file = models.FileField(upload_to='uploads/%Y/%m/%d') | |
| 167 | - name = models.CharField(max_length=100) | |
| 168 | 160 | |
| 169 | 161 | """ |
| 170 | 162 | It is a category for each subject. | ... | ... |
courses/templates/exercise/create_exercise.html
| ... | ... | @@ -1,74 +0,0 @@ |
| 1 | -{% load widget_tweaks i18n %} | |
| 2 | -<!--MODAL CREATE LINK--> | |
| 3 | -<div class="modal fade" id="createLinksModal" tabindex="-1" role="dialog" aria-labelledby="createLink"> | |
| 4 | - <div class="modal-dialog" role="document"> | |
| 5 | - <div class="modal-content"> | |
| 6 | - <div class="modal-header"> | |
| 7 | - <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
| 8 | - <h4 class="modal-title" id="createLink">{% trans 'Create a New Exercise' %}</h4> | |
| 9 | - </div> | |
| 10 | - <div class="modal-body"> | |
| 11 | - <!-- Card --> | |
| 12 | - <form method="post" action="" id="form-link" enctype="multipart/form-data"> | |
| 13 | - {% csrf_token %} | |
| 14 | - {% for field in form %} | |
| 15 | - <div class ="form-group"> | |
| 16 | - {% if field.field.required %} | |
| 17 | - <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label> | |
| 18 | - {% endif %} | |
| 19 | - {% render_field field class='form-control input-sm' %} | |
| 20 | - {% if field.errors %} | |
| 21 | - <div class="alert alert-danger alert-dismissible clearfix" role="alert"> | |
| 22 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
| 23 | - <span aria-hidden="true">×</span> | |
| 24 | - </button> | |
| 25 | - <ul> | |
| 26 | - {% for error in field.errors %} | |
| 27 | - <li>{{ error }}</li> | |
| 28 | - {% endfor %} | |
| 29 | - </ul> | |
| 30 | - </div> | |
| 31 | - {% endif %} | |
| 32 | - </div> | |
| 33 | - {% endfor %} | |
| 34 | - <div class="form-group"> | |
| 35 | - <button type="button" class="btn btn-raised btn-default " data-dismiss="modal">{% trans "Cancel" %}</button> | |
| 36 | - <button class="btn btn-raised btn-primary" type="submit">{% trans 'Submit' %}</button> | |
| 37 | - </div> | |
| 38 | - <!-- .end Card --> | |
| 39 | - </div> | |
| 40 | - </div> | |
| 41 | - </div> | |
| 42 | -</div> | |
| 43 | -<!-- EndModal --> | |
| 44 | -{% block script_link %} | |
| 45 | - {# // <script src="{% static 'js/links.js' %}"></script> #} | |
| 46 | - <script type="text/javascript"> | |
| 47 | - $("#form-link").submit(function(event) { | |
| 48 | - $("#createLinksModal").modal("hide"); | |
| 49 | - var data = new FormData($('#form-link').get(0)); | |
| 50 | - $.ajax({ | |
| 51 | - url: "{% url 'course:links:create_link' topic.slug %}", | |
| 52 | - type: $("#form-link").attr('method'), | |
| 53 | - data: data, | |
| 54 | - cache: false, | |
| 55 | - processData: false, | |
| 56 | - contentType: false, | |
| 57 | - success: function(data) { | |
| 58 | - $('#requisicoes_ajax').empty(); | |
| 59 | - $('#list-topic{{ topic.id }}-links').append(data); | |
| 60 | - $('#list-topic{{ topic.id }}-links-edit').append(data); | |
| 61 | - alertify.alert('Link successfully created!') | |
| 62 | - }, | |
| 63 | - error: function(data){ | |
| 64 | - $("div.modal-backdrop.fade.in").remove(); | |
| 65 | - $('#requisicoes_ajax').empty(); | |
| 66 | - $('#requisicoes_ajax').append(data.responseText); | |
| 67 | - $('#createLinksModal').modal('show'); | |
| 68 | - alertify.alert('Invalid link, insert a valid one!'); | |
| 69 | - } | |
| 70 | - }); | |
| 71 | - event.preventDefault(); | |
| 72 | - }); | |
| 73 | - </script> | |
| 74 | -{% endblock script_link %} | |
| 75 | 0 | \ No newline at end of file |
courses/templates/exercise/exercise_edit.html
| ... | ... | @@ -1,7 +0,0 @@ |
| 1 | -{% load static i18n list_topic_foruns permission_tags %} | |
| 2 | -<div id="exercise-topic{{ exercise.id }}-exercises-edit"> | |
| 3 | - {% for exercise in exercises %} | |
| 4 | - <li class="icon_edit_remove" id = "exercise_edit_icon_{{ exercise.slug }}"> <a href="javascript:modal.get('{% url 'course:update_exercise' exercise.slug %}', '#exercisesModalEdit', '#requisicoes_ajax')"><i class="fa fa-pencil fa-lg" aria-hidden="true"></i></a> <a href="javascript:modal.get('{% url 'course:delete_exercise' exercise.slug %}', '#exerciseDeleteModal', '#requisicoes_ajax')"><i class="fa fa-trash fa-lg" aria-hidden="true"></i></a></li> | |
| 5 | - <li id = "exercise_edit_{{ exercise.slug }}"><i class="fa fa-link" aria-hidden="true"></i> <a href="javascript:modal.get('{% url 'course:view_exercise' exercise.slug %}', '#viewExerciseModal','#requisicoes_ajax')">{{exercise.name}}</a></li> | |
| 6 | - {% endfor %} | |
| 7 | -</div> |
courses/templates/exercise/exercise_list.html
| ... | ... | @@ -1,6 +0,0 @@ |
| 1 | -{% load static i18n list_topic_foruns permission_tags %} | |
| 2 | -<div id="list-topic{{ topic.id }}-exercises"> | |
| 3 | -{% for exercise in exercises %} | |
| 4 | - <li id = "exercise_{{ exercise.slug }}"><i class="fa fa-link" aria-hidden="true"></i> <a href="javascript:modal.get('{% url 'course:view_exercise' exercise.slug %}', '#viewExerciseModal','#requisicoes_ajax')">{{exercise.name}}</a></li> | |
| 5 | -{% endfor %} | |
| 6 | -</div> |
courses/templates/subject/form_view_student.html
| ... | ... | @@ -67,6 +67,15 @@ |
| 67 | 67 | <div class="resource_inline"> |
| 68 | 68 | <h4>{% trans 'Exercises' %}</h4> |
| 69 | 69 | </div> |
| 70 | + <div class="resource_inline"> | |
| 71 | + {# dropdown de create exercício #} | |
| 72 | + <div class="dropdown"> | |
| 73 | + <a href="#" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-plus-circle fa-lg" aria-hidden="true"></i></a> | |
| 74 | + <ul class="dropdown-menu" aria-labelledby="dLabel"> | |
| 75 | + <li><a href="javascript:modal.get('{% url 'course:exercise:create_exercise' topic.slug %}', '#createExercisesModal','#requisicoes_ajax')">{% trans 'Create a Exercise' %}</a></li> | |
| 76 | + </ul> | |
| 77 | + </div> | |
| 78 | + </div> | |
| 70 | 79 | <div class="presentation_{{exercise.slug}}"> |
| 71 | 80 | {# exercício do tópico no modo de visualização #} |
| 72 | 81 | <ul> | ... | ... |
courses/templatetags/list_topic_exercises.py
| ... | ... | @@ -1,25 +0,0 @@ |
| 1 | -from django import template | |
| 2 | -from courses.models import Exercise | |
| 3 | - | |
| 4 | -register = template.Library() | |
| 5 | - | |
| 6 | - | |
| 7 | -@register.inclusion_tag('exercise/exercise_list.html') | |
| 8 | -def list_topic_exercise(request): | |
| 9 | - context = { | |
| 10 | - 'request': request, | |
| 11 | - } | |
| 12 | - context['exercises'] = Exercise.objects.all() | |
| 13 | - | |
| 14 | - return context | |
| 15 | - | |
| 16 | - | |
| 17 | -@register.inclusion_tag('exercise/exercise_edit.html') | |
| 18 | -def list_topic_exercise_edit(request, exercise): | |
| 19 | - context = { | |
| 20 | - 'request': request, | |
| 21 | - } | |
| 22 | - context['exercises'] = Exercise.objects.all() | |
| 23 | - context['exercise'] = exercise | |
| 24 | - | |
| 25 | - return context |
courses/urls.py
| ... | ... | @@ -2,38 +2,39 @@ from django.conf.urls import url, include |
| 2 | 2 | |
| 3 | 3 | from . import views |
| 4 | 4 | urlpatterns = [ |
| 5 | - url(r'^$', views.IndexView.as_view(), name='manage'), | |
| 6 | - url(r'^all-courses/$', views.AllCoursesView.as_view(), name='all_courses'), | |
| 7 | - url(r'^create/$', views.CreateCourseView.as_view(), name='create'), | |
| 8 | - url(r'^replicate_course/(?P<slug>[\w_-]+)/$', views.ReplicateCourseView.as_view(), name='replicate_course'), | |
| 9 | - url(r'^replicate_subject/(?P<slug>[\w_-]+)/$', views.ReplicateSubjectView.as_view(), name='replicate_subject'), | |
| 10 | - url(r'^edit/(?P<slug>[\w_-]+)/$', views.UpdateCourseView.as_view(), name='update'), | |
| 11 | - url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteCourseView.as_view(), name='delete'), | |
| 12 | - url(r'^subscribe/(?P<slug>[\w_-]+)/$', views.subscribe_course, name='subscribe'), | |
| 13 | - url(r'^category/(?P<slug>[\w_-]+)/$', views.FilteredView.as_view(), name='filter'), | |
| 14 | - url(r'^categories/view/$', views.IndexCatView.as_view(), name='manage_cat'), | |
| 15 | - url(r'^categories/create/$', views.CreateCatView.as_view(), name="create_cat"), | |
| 16 | - url(r'^categories/edit/(?P<slug>[\w_-]+)/$', views.UpdateCatView.as_view(), name='update_cat'), | |
| 17 | - url(r'^categories/delete/(?P<slug>[\w_-]+)/$', views.DeleteCatView.as_view(), name='delete_cat'), | |
| 18 | - url(r'^subjects/(?P<slug>[\w_-]+)/$', views.SubjectsView.as_view(), name='view_subject'), | |
| 19 | - url(r'^subjects/create/(?P<slug>[\w_-]+)/$', views.CreateSubjectView.as_view(), name='create_subject'), | |
| 20 | - url(r'^subjects/update/(?P<slug>[\w_-]+)/$', views.UpdateSubjectView.as_view(), name='update_subject'), | |
| 21 | - url(r'^subjects/delete/(?P<slug>[\w_-]+)/$', views.DeleteSubjectView.as_view(), name='delete_subject'), | |
| 22 | - url(r'^subjects/subscribe/(?P<slug>[\w_-]+)/$', views.subscribe_subject, name='subscribe_subject'), | |
| 23 | - url(r'^topics/create/(?P<slug>[\w_-]+)/$', views.CreateTopicView.as_view(), name='create_topic'), | |
| 24 | - url(r'^topics/update/(?P<slug>[\w_-]+)/$', views.UpdateTopicView.as_view(), name='update_topic'), | |
| 25 | - url(r'^topics/update/(?P<slug>[\w_-]+)/$', views.DeleteTopic.as_view(), name='update_topic'), | |
| 26 | - url(r'^topics/(?P<slug>[\w_-]+)/$', views.TopicsView.as_view(), name='view_topic'), | |
| 27 | - url(r'^subjects/categories$',views.IndexSubjectCategoryView.as_view(), name='subject_category_index'), | |
| 28 | - url(r'^forum/', include('forum.urls', namespace = 'forum')), | |
| 29 | - url(r'^poll/', include('poll.urls', namespace = 'poll')), | |
| 30 | - url(r'^exam/', include('exam.urls', namespace = 'exam')), | |
| 31 | - url(r'^files/', include('files.urls', namespace = 'file')), | |
| 32 | - url(r'^upload-material/$', views.UploadMaterialView.as_view(), name='upload_material'), | |
| 33 | - url(r'^subjects/file-material-view/(?P<slug>[\w_-]+)/$', views.FileMaterialView.as_view(), name='file_material_view'), | |
| 34 | - url(r'^links/',include('links.urls',namespace = 'links')), | |
| 35 | - url(r'^(?P<slug>[\w_-]+)/', include([ | |
| 36 | - url(r'^$', views.CourseView.as_view(), name='view'), | |
| 37 | - url(r'^(?P<category>[\w_-]+)/$', views.CourseView.as_view(), name='view_filter') | |
| 38 | - ])), | |
| 5 | + url(r'^$', views.IndexView.as_view(), name='manage'), | |
| 6 | + url(r'^all-courses/$', views.AllCoursesView.as_view(), name='all_courses'), | |
| 7 | + url(r'^create/$', views.CreateCourseView.as_view(), name='create'), | |
| 8 | + url(r'^replicate_course/(?P<slug>[\w_-]+)/$', views.ReplicateCourseView.as_view(), name='replicate_course'), | |
| 9 | + url(r'^replicate_subject/(?P<slug>[\w_-]+)/$', views.ReplicateSubjectView.as_view(), name='replicate_subject'), | |
| 10 | + url(r'^edit/(?P<slug>[\w_-]+)/$', views.UpdateCourseView.as_view(), name='update'), | |
| 11 | + url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteCourseView.as_view(), name='delete'), | |
| 12 | + url(r'^subscribe/(?P<slug>[\w_-]+)/$', views.subscribe_course, name='subscribe'), | |
| 13 | + url(r'^category/(?P<slug>[\w_-]+)/$', views.FilteredView.as_view(), name='filter'), | |
| 14 | + url(r'^categories/view/$', views.IndexCatView.as_view(), name='manage_cat'), | |
| 15 | + url(r'^categories/create/$', views.CreateCatView.as_view(), name="create_cat"), | |
| 16 | + url(r'^categories/edit/(?P<slug>[\w_-]+)/$', views.UpdateCatView.as_view(), name='update_cat'), | |
| 17 | + url(r'^categories/delete/(?P<slug>[\w_-]+)/$', views.DeleteCatView.as_view(), name='delete_cat'), | |
| 18 | + url(r'^subjects/(?P<slug>[\w_-]+)/$', views.SubjectsView.as_view(), name='view_subject'), | |
| 19 | + url(r'^subjects/create/(?P<slug>[\w_-]+)/$', views.CreateSubjectView.as_view(), name='create_subject'), | |
| 20 | + url(r'^subjects/update/(?P<slug>[\w_-]+)/$', views.UpdateSubjectView.as_view(), name='update_subject'), | |
| 21 | + url(r'^subjects/delete/(?P<slug>[\w_-]+)/$', views.DeleteSubjectView.as_view(), name='delete_subject'), | |
| 22 | + url(r'^subjects/subscribe/(?P<slug>[\w_-]+)/$', views.subscribe_subject, name='subscribe_subject'), | |
| 23 | + url(r'^topics/create/(?P<slug>[\w_-]+)/$', views.CreateTopicView.as_view(), name='create_topic'), | |
| 24 | + url(r'^topics/update/(?P<slug>[\w_-]+)/$', views.UpdateTopicView.as_view(), name='update_topic'), | |
| 25 | + url(r'^topics/update/(?P<slug>[\w_-]+)/$', views.DeleteTopic.as_view(), name='update_topic'), | |
| 26 | + url(r'^topics/(?P<slug>[\w_-]+)/$', views.TopicsView.as_view(), name='view_topic'), | |
| 27 | + url(r'^subjects/categories$',views.IndexSubjectCategoryView.as_view(), name='subject_category_index'), | |
| 28 | + url(r'^forum/', include('forum.urls', namespace = 'forum')), | |
| 29 | + url(r'^poll/', include('poll.urls', namespace = 'poll')), | |
| 30 | + url(r'^exam/', include('exam.urls', namespace = 'exam')), | |
| 31 | + url(r'^files/', include('files.urls', namespace = 'file')), | |
| 32 | + url(r'^upload-material/$', views.UploadMaterialView.as_view(), name='upload_material'), | |
| 33 | + url(r'^subjects/file-material-view/(?P<slug>[\w_-]+)/$', views.FileMaterialView.as_view(), name='file_material_view'), | |
| 34 | + url(r'^links/',include('links.urls',namespace = 'links')), | |
| 35 | + url(r'^exercise/', include('exercise.urls', namespace='exercise')), | |
| 36 | + url(r'^(?P<slug>[\w_-]+)/', include([ | |
| 37 | + url(r'^$', views.CourseView.as_view(), name='view'), | |
| 38 | + url(r'^(?P<category>[\w_-]+)/$', views.CourseView.as_view(), name='view_filter') | |
| 39 | + ])), | |
| 39 | 40 | ] | ... | ... |
courses/views.py
| 1 | -from django.shortcuts import get_object_or_404 | |
| 2 | -from django.views import generic | |
| 1 | +from .forms import CourseForm, UpdateCourseForm, CategoryCourseForm, SubjectForm,TopicForm,ActivityForm | |
| 2 | +from .models import Course, Subject, CourseCategory, Topic, SubjectCategory, Activity, CategorySubject | |
| 3 | +from core.decorators import log_decorator | |
| 4 | +from core.mixins import LogMixin, NotificationMixin | |
| 5 | +from core.models import Log | |
| 6 | +from courses.models import Material | |
| 7 | +from datetime import date, datetime | |
| 3 | 8 | from django.contrib import messages |
| 4 | 9 | from django.contrib.auth.decorators import login_required |
| 5 | -from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger | |
| 6 | 10 | from django.contrib.auth.mixins import LoginRequiredMixin |
| 7 | -from rolepermissions.mixins import HasRoleMixin | |
| 11 | +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger | |
| 8 | 12 | from django.core.urlresolvers import reverse_lazy |
| 9 | -from django.utils.translation import ugettext_lazy as _ | |
| 10 | -from rolepermissions.verifications import has_role | |
| 11 | 13 | from django.db.models import Q |
| 12 | -import operator | |
| 13 | -from functools import reduce | |
| 14 | -from rolepermissions.verifications import has_object_permission | |
| 15 | 14 | from django.http import JsonResponse |
| 16 | -from .forms import CourseForm, UpdateCourseForm, CategoryCourseForm, SubjectForm,TopicForm,ActivityForm | |
| 17 | -from .models import Course, Subject, CourseCategory,Topic, Exercise, SubjectCategory,Activity, CategorySubject | |
| 18 | -from core.decorators import log_decorator | |
| 19 | -from core.mixins import LogMixin, NotificationMixin | |
| 20 | -from core.models import Log | |
| 21 | -from users.models import User | |
| 15 | +from django.shortcuts import get_object_or_404 | |
| 16 | +from django.urls import reverse | |
| 17 | +from django.utils.translation import ugettext_lazy as _ | |
| 18 | +from django.views import generic | |
| 19 | +from exercise.models import Exercise | |
| 22 | 20 | from files.forms import FileForm |
| 23 | 21 | from files.models import TopicFile |
| 24 | -from courses.models import Material | |
| 25 | -from django.urls import reverse | |
| 26 | - | |
| 27 | -from datetime import date, datetime | |
| 22 | +from functools import reduce | |
| 23 | +from rolepermissions.mixins import HasRoleMixin | |
| 24 | +from rolepermissions.verifications import has_object_permission | |
| 25 | +from rolepermissions.verifications import has_role | |
| 26 | +from users.models import User | |
| 27 | +import operator | |
| 28 | 28 | import time |
| 29 | 29 | |
| 30 | 30 | #API IMPORTS |
| ... | ... | @@ -566,7 +566,7 @@ class SubjectsView(LoginRequiredMixin, LogMixin, generic.ListView): |
| 566 | 566 | context['course'] = subject.course |
| 567 | 567 | context['subject'] = subject |
| 568 | 568 | context['topics'] = Topic.objects.filter(subject = subject) |
| 569 | - context['exercise'] = Exercise.objects.filter(exercise__topic__subject=subject) | |
| 569 | + context['exercise'] = Exercise.objects.filter(topic__subject=subject) | |
| 570 | 570 | if has_role(self.request.user,'professor') or has_role(self.request.user,'system_admin'): |
| 571 | 571 | context['files'] = TopicFile.objects.filter(professor__name = self.request.user.name) |
| 572 | 572 | else: | ... | ... |
exam/migrations/0001_initial.py
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | -# Generated by Django 1.10 on 2016-11-13 17:47 | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 3 | 3 | from __future__ import unicode_literals |
| 4 | 4 | |
| 5 | -from django.conf import settings | |
| 6 | 5 | from django.db import migrations, models |
| 7 | 6 | import django.db.models.deletion |
| 8 | 7 | |
| ... | ... | @@ -13,7 +12,6 @@ class Migration(migrations.Migration): |
| 13 | 12 | |
| 14 | 13 | dependencies = [ |
| 15 | 14 | ('courses', '0001_initial'), |
| 16 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 17 | 15 | ] |
| 18 | 16 | |
| 19 | 17 | operations = [ |
| ... | ... | @@ -25,9 +23,9 @@ class Migration(migrations.Migration): |
| 25 | 23 | ('order', models.PositiveSmallIntegerField(verbose_name='Order')), |
| 26 | 24 | ], |
| 27 | 25 | options={ |
| 26 | + 'ordering': ('order',), | |
| 28 | 27 | 'verbose_name': 'Answer', |
| 29 | 28 | 'verbose_name_plural': 'Answers', |
| 30 | - 'ordering': ('order',), | |
| 31 | 29 | }, |
| 32 | 30 | ), |
| 33 | 31 | migrations.CreateModel( |
| ... | ... | @@ -61,14 +59,4 @@ class Migration(migrations.Migration): |
| 61 | 59 | name='exam', |
| 62 | 60 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student_exam', to='exam.Exam', verbose_name='Exam'), |
| 63 | 61 | ), |
| 64 | - migrations.AddField( | |
| 65 | - model_name='answersstudent', | |
| 66 | - name='student', | |
| 67 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student', to=settings.AUTH_USER_MODEL, verbose_name='Student'), | |
| 68 | - ), | |
| 69 | - migrations.AddField( | |
| 70 | - model_name='answer', | |
| 71 | - name='exam', | |
| 72 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='exam.Exam', verbose_name='Answers'), | |
| 73 | - ), | |
| 74 | 62 | ] | ... | ... |
| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 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 | + initial = True | |
| 13 | + | |
| 14 | + dependencies = [ | |
| 15 | + ('exam', '0001_initial'), | |
| 16 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 17 | + ] | |
| 18 | + | |
| 19 | + operations = [ | |
| 20 | + migrations.AddField( | |
| 21 | + model_name='answersstudent', | |
| 22 | + name='student', | |
| 23 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student', to=settings.AUTH_USER_MODEL, verbose_name='Student'), | |
| 24 | + ), | |
| 25 | + migrations.AddField( | |
| 26 | + model_name='answer', | |
| 27 | + name='exam', | |
| 28 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='exam.Exam', verbose_name='Answers'), | |
| 29 | + ), | |
| 30 | + ] | ... | ... |
| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | +from .models import Exercise | |
| 2 | +from django import forms | |
| 3 | +from django.core.exceptions import ValidationError, FieldError | |
| 4 | +from django.utils.translation import ugettext_lazy as _ | |
| 5 | +import requests | |
| 6 | + | |
| 7 | + | |
| 8 | +class ExerciseForm(forms.ModelForm): | |
| 9 | + | |
| 10 | + class Meta: | |
| 11 | + model = Exercise | |
| 12 | + fields = ['name', 'file'] | |
| 13 | + | |
| 14 | + | |
| 15 | +class UpdateExerciseForm(forms.ModelForm): | |
| 16 | + | |
| 17 | + class Meta: | |
| 18 | + model = Exercise | |
| 19 | + fields = ['name', 'file'] | ... | ... |
| ... | ... | @@ -0,0 +1,27 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 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 | + initial = True | |
| 12 | + | |
| 13 | + dependencies = [ | |
| 14 | + ('courses', '0001_initial'), | |
| 15 | + ] | |
| 16 | + | |
| 17 | + operations = [ | |
| 18 | + migrations.CreateModel( | |
| 19 | + name='Exercise', | |
| 20 | + fields=[ | |
| 21 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
| 22 | + ('file', models.FileField(upload_to='uploads/%Y/%m/%d')), | |
| 23 | + ('name', models.CharField(max_length=100)), | |
| 24 | + ('topic', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='exercises', to='courses.Topic', verbose_name='Topic')), | |
| 25 | + ], | |
| 26 | + ), | |
| 27 | + ] | ... | ... |
| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | +from django.db import models | |
| 2 | +from courses.models import Topic | |
| 3 | +from django.utils.translation import ugettext_lazy as _ | |
| 4 | + | |
| 5 | +""" | |
| 6 | + Function to return the path where the file should be saved | |
| 7 | +""" | |
| 8 | + | |
| 9 | + | |
| 10 | +def file_path(instance, filename): | |
| 11 | + return '/'.join([instance.topic.subject.course.slug, instance.topic.subject.slug, instance.topic.slug, filename]) | |
| 12 | + | |
| 13 | + | |
| 14 | +""" | |
| 15 | +It represents the Exercises inside topic. | |
| 16 | +""" | |
| 17 | + | |
| 18 | + | |
| 19 | +class Exercise(models.Model): | |
| 20 | + topic = models.ForeignKey(Topic, verbose_name=_('Topic'), related_name='exercises') | |
| 21 | + file = models.FileField(upload_to='uploads/%Y/%m/%d') | |
| 22 | + name = models.CharField(max_length=100) | ... | ... |
| ... | ... | @@ -0,0 +1,82 @@ |
| 1 | +{% load widget_tweaks i18n static %} | |
| 2 | +<!--MODAL CREATE EXERCISE--> | |
| 3 | +<div class="modal fade" id="createExercisesModal" tabindex="-1" role="dialog" aria-labelledby="createExercise"> | |
| 4 | + <div class="modal-dialog" role="document"> | |
| 5 | + <div class="modal-content"> | |
| 6 | + <div class="modal-header"> | |
| 7 | + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
| 8 | + <h4 class="modal-title" id="createExercise">{% trans 'Create a New Exercise' %}</h4> | |
| 9 | + </div> | |
| 10 | + <div class="modal-body"> | |
| 11 | + <!-- Card --> | |
| 12 | + <form method="post" action="" id="form-exercise" enctype="multipart/form-data"> | |
| 13 | + {% csrf_token %} | |
| 14 | + {% if messages %} | |
| 15 | + {% for message in messages %} | |
| 16 | + <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert"> | |
| 17 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
| 18 | + <span aria-hidden="true">×</span> | |
| 19 | + </button> | |
| 20 | + <p>{{ message }}</p> | |
| 21 | + </div> | |
| 22 | + {% endfor %} | |
| 23 | + {% endif %} | |
| 24 | + {% for field in form %} | |
| 25 | + <div class ="form-group"> | |
| 26 | + {% if field.field.required %} | |
| 27 | + <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label> | |
| 28 | + {% endif %} | |
| 29 | + {% render_field field class='form-control input-sm' %} | |
| 30 | + {% if field.errors %} | |
| 31 | + <div class="alert alert-danger alert-dismissible clearfix" role="alert"> | |
| 32 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
| 33 | + <span aria-hidden="true">×</span> | |
| 34 | + </button> | |
| 35 | + <ul> | |
| 36 | + {% for error in field.errors %} | |
| 37 | + <li>{{ error }}</li> | |
| 38 | + {% endfor %} | |
| 39 | + </ul> | |
| 40 | + </div> | |
| 41 | + {% endif %} | |
| 42 | + </div> | |
| 43 | + {% endfor %} | |
| 44 | + <div class="form-group"> | |
| 45 | + <button type="button" class="btn btn-raised btn-default " data-dismiss="modal">{% trans "Cancel" %}</button> | |
| 46 | + <button class="btn btn-raised btn-primary" type="submit">{% trans 'Submit' %}</button> | |
| 47 | + </div> | |
| 48 | + <!-- .end Card --> | |
| 49 | + </div> | |
| 50 | + </div> | |
| 51 | + </div> | |
| 52 | +</div> | |
| 53 | +<!-- EndModal --> | |
| 54 | +<script src="{% static 'js/exercises.js' %}"></script> | |
| 55 | +<script type="text/javascript"> | |
| 56 | + $("#form-exercise").submit(function(event) { | |
| 57 | + $("#createExercisesModal").modal("hide"); | |
| 58 | + var data = new FormData($('#form-exercise').get(0)); | |
| 59 | + $.ajax({ | |
| 60 | + url: "{% url 'course:exercise:create_exercise' topic.slug %}", | |
| 61 | + type: $("#form-exercise").attr('method'), | |
| 62 | + data: data, | |
| 63 | + cache: false, | |
| 64 | + processData: false, | |
| 65 | + contentType: false, | |
| 66 | + success: function(data) { | |
| 67 | + $('#requisicoes_ajax').empty(); | |
| 68 | + $('#list-topic{{ topic.id }}-exercises').append(data); | |
| 69 | + $('#list-topic{{ topic.id }}-exercises-edit').append(data); | |
| 70 | + alertify.success('Exercise successfully created!') | |
| 71 | + }, | |
| 72 | + error: function(data){ | |
| 73 | + $('#requisicoes_ajax').empty(); | |
| 74 | + $('#requisicoes_ajax').append(data.responseText); | |
| 75 | + $('#createExercisesModal').modal('show'); | |
| 76 | + alertify.alert('Invalid exercise, insert a valid one!'); | |
| 77 | + $('div.modal-backdrop.fade.in').remove(); | |
| 78 | + } | |
| 79 | + }); | |
| 80 | + event.preventDefault(); | |
| 81 | + }); | |
| 82 | +</script> | ... | ... |
| ... | ... | @@ -0,0 +1,66 @@ |
| 1 | +{% load static widget_tweaks i18n %} | |
| 2 | + | |
| 3 | +<!-- MODAL DELETE LINK --> | |
| 4 | +<exercise rel="stylesheet" type="text/css" href="{% static 'css/exercise.css' %}"> | |
| 5 | + | |
| 6 | +<div class="erro-update"> | |
| 7 | + <div class="modal fade" id="exerciseDeleteModal" tabindex="-1" role="dialog" aria-labelledby="deleteExerciseLabel" style="z-index: 10"> | |
| 8 | + <div class="modal-dialog" role="document"> | |
| 9 | + <div class="modal-content"> | |
| 10 | + <div class="modal-header"> | |
| 11 | + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
| 12 | + <h4 class="modal-title" id="deleteExerciseLabel">{% trans 'Delete Exercise' %}</h4> | |
| 13 | + </div> | |
| 14 | + <div class="modal-body"> | |
| 15 | + <!-- Card --> | |
| 16 | + <form class="form-horizontal" method="post" id="form-delete-exercise" enctype="multipart/form-data"> | |
| 17 | + {% csrf_token %} | |
| 18 | + <fieldset> | |
| 19 | + <div class="col-md-12"> | |
| 20 | + {% trans "Are you sure to delete the exercise " %} <strong>"{{ exercise.name }}"</strong> </a> of {{ exercise.topic.name }}? | |
| 21 | + </div> | |
| 22 | + <div class="form-group"> | |
| 23 | + <div class="col-md-12"> | |
| 24 | + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button> | |
| 25 | + <button class="btn btn-raised btn-primary" type="submit">{% trans 'Delete' %}</button> | |
| 26 | + </div> | |
| 27 | + </div> | |
| 28 | + </fieldset> | |
| 29 | + </form> | |
| 30 | + <!-- .end Card --> | |
| 31 | + </div> | |
| 32 | + </div> | |
| 33 | + </div> | |
| 34 | + </div> | |
| 35 | +</div> | |
| 36 | + <script src="{% static 'js/exercise.js' %}"></script> | |
| 37 | + <script type="text/javascript"> | |
| 38 | + $("#form-delete-exercise").submit(function(event) { | |
| 39 | + var data = new FormData($('#form-delete-exercise').get(0)); | |
| 40 | + $('#exerciseDeleteModal').modal('hide'); | |
| 41 | + $.ajax({ | |
| 42 | + url: "{% url 'course:exercises:delete_exercise' exercise.slug %}", | |
| 43 | + type: $("#form-delete-exercise").attr('method'), | |
| 44 | + data: data, | |
| 45 | + cache: false, | |
| 46 | + processData: false, | |
| 47 | + contentType: false, | |
| 48 | + success: function(data) { | |
| 49 | + $('#requisicoes_ajax').empty(); | |
| 50 | + $('#exercise_{{ exercise.slug }}').remove(); | |
| 51 | + $('#exercise_edit_icon_{{ exercise.slug }}').remove(); | |
| 52 | + $('#exercise_edit_{{ exercise.slug }}').remove(); | |
| 53 | + alertify.alert('Exercise successfully deleted!') | |
| 54 | + }, | |
| 55 | + error: function(data){ | |
| 56 | + $("div.modal-backdrop.fade.in").remove(); | |
| 57 | + $('#requisicoes_ajax').empty(); | |
| 58 | + $('#requisicoes_ajax').append(data.responseText); | |
| 59 | + $('#exerciseDeleteModal').modal('show'); | |
| 60 | + alertify.alert('Error when trying to delete.'); | |
| 61 | + } | |
| 62 | + }); | |
| 63 | + event.preventDefault(); | |
| 64 | + }); | |
| 65 | + </script> | |
| 66 | +<!-- EndModal --> | ... | ... |
| ... | ... | @@ -0,0 +1,7 @@ |
| 1 | +{% load static i18n list_topic_foruns permission_tags %} | |
| 2 | +<div id="exercise-topic{{ exercise.id }}-exercises-edit"> | |
| 3 | + {% for exercise in exercises %} | |
| 4 | + <li class="icon_edit_remove" id = "exercise_edit_icon_{{ exercise.slug }}"> <a href="javascript:modal.get('', '#exercisesModalEdit', '#requisicoes_ajax')"><i class="fa fa-pencil fa-lg" aria-hidden="true"></i></a> <a href="javascript:modal.get('', '#exerciseDeleteModal', '#requisicoes_ajax')"><i class="fa fa-trash fa-lg" aria-hidden="true"></i></a></li> | |
| 5 | + <li id = "exercise_edit_{{ exercise.slug }}"><i class="fa fa-link" aria-hidden="true"></i> <a href="javascript:modal.get('', '#viewExerciseModal','#requisicoes_ajax')">{{exercise.name}}</a></li> | |
| 6 | + {% endfor %} | |
| 7 | +</div> | ... | ... |
| ... | ... | @@ -0,0 +1,6 @@ |
| 1 | +{% load static i18n list_topic_foruns permission_tags %} | |
| 2 | +<div id="list-topic{{ topic.id }}-exercises"> | |
| 3 | +{% for exercise in exercises %} | |
| 4 | + <li id="exercise_{{ exercise.slug }}"><i class="fa fa-link" aria-hidden="true"></i> <a href="{{exercise.file.url}}">{{exercise.name}}</a></li> | |
| 5 | +{% endfor %} | |
| 6 | +</div> | ... | ... |
| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | +from django import template | |
| 2 | +from exercise.models import Exercise | |
| 3 | + | |
| 4 | +register = template.Library() | |
| 5 | + | |
| 6 | + | |
| 7 | +@register.inclusion_tag('exercise/exercise_list.html') | |
| 8 | +def list_topic_exercise(request): | |
| 9 | + context = { | |
| 10 | + 'request': request, | |
| 11 | + } | |
| 12 | + context['exercises'] = Exercise.objects.all() | |
| 13 | + | |
| 14 | + return context | |
| 15 | + | |
| 16 | + | |
| 17 | +@register.inclusion_tag('exercise/exercise_edit.html') | |
| 18 | +def list_topic_exercise_edit(request, exercise): | |
| 19 | + context = { | |
| 20 | + 'request': request, | |
| 21 | + } | |
| 22 | + context['exercises'] = Exercise.objects.all() | |
| 23 | + context['exercise'] = exercise | |
| 24 | + | |
| 25 | + return context | ... | ... |
| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | +from django.conf.urls import url | |
| 2 | +from . import views | |
| 3 | + | |
| 4 | +urlpatterns = [ | |
| 5 | + url(r'^create_exercise/(?P<slug>[\w_-]+)/$', views.CreateExercise.as_view(), name='create_exercise'), | |
| 6 | + url(r'^delete_exercise/(?P<slug>[\w_-]+)/$', views.DeleteExercise.as_view(), name='delete_exercise'), | |
| 7 | + url(r'^update_exercise/(?P<slug>[\w_-]+)/$', views.UpdateExercise.as_view(), name='update_exercise'), | |
| 8 | + url(r'^render-exercise/(?P<id>[0-9]+)/$', views.render_exercise, name='render_exercise'), | |
| 9 | +] | ... | ... |
| ... | ... | @@ -0,0 +1,253 @@ |
| 1 | +from .forms import ExerciseForm, UpdateExerciseForm | |
| 2 | +from .models import Exercise | |
| 3 | +from files.utils import mime_type_to_material_icons | |
| 4 | +from core.decorators import log_decorator | |
| 5 | +from core.mixins import LogMixin, NotificationMixin | |
| 6 | +from core.models import Log, MimeType | |
| 7 | +from courses.models import Topic | |
| 8 | +from datetime import datetime | |
| 9 | +from django.conf import settings | |
| 10 | +from django.contrib import messages | |
| 11 | +from django.contrib.auth.mixins import LoginRequiredMixin | |
| 12 | +from django.core.urlresolvers import reverse_lazy | |
| 13 | +from django.shortcuts import render, get_object_or_404, redirect | |
| 14 | +from django.urls import reverse | |
| 15 | +from django.views import generic | |
| 16 | +from rolepermissions.mixins import HasRoleMixin | |
| 17 | +from rolepermissions.verifications import has_role | |
| 18 | + | |
| 19 | + | |
| 20 | +class CreateExercise(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin, generic.CreateView): | |
| 21 | + log_component = 'exercise' | |
| 22 | + log_resource = 'exercise' | |
| 23 | + log_action = 'create' | |
| 24 | + log_component = {} | |
| 25 | + | |
| 26 | + allowed_roles = ['student'] | |
| 27 | + login_url = reverse_lazy("core:home") | |
| 28 | + redirect_field_name = 'next' | |
| 29 | + model = Exercise | |
| 30 | + template_name = 'exercise/create_exercise.html' | |
| 31 | + form_class = ExerciseForm | |
| 32 | + success_url = reverse_lazy('course:exercise:render_exercise') | |
| 33 | + | |
| 34 | + log_component = "subject" | |
| 35 | + log_resource = "exercise" | |
| 36 | + log_action = "create" | |
| 37 | + log_context = {} | |
| 38 | + context_object_name = 'form' | |
| 39 | + | |
| 40 | + def form_invalid(self, form, **kwargs): | |
| 41 | + context = super(CreateExercise, self).form_invalid(form) | |
| 42 | + context.status_code = 400 | |
| 43 | + | |
| 44 | + return context | |
| 45 | + | |
| 46 | + def form_valid(self, form): | |
| 47 | + self.object = form.save(commit = False) | |
| 48 | + topic = get_object_or_404(Topic, slug = self.kwargs.get('slug')) | |
| 49 | + self.object.topic = topic | |
| 50 | + | |
| 51 | + self.object.name = str(self.object) | |
| 52 | + | |
| 53 | + | |
| 54 | + # Set MimeType | |
| 55 | + exercise = self.request.FILES['exercise_url'] | |
| 56 | + try: | |
| 57 | + if exercise: | |
| 58 | + exercise_type = exercise.content_type | |
| 59 | + | |
| 60 | + # Check if exist a mimetype in database | |
| 61 | + try: | |
| 62 | + self.object.exercise_type = MimeType.objects.get(typ = exercise_type) | |
| 63 | + # Create if not | |
| 64 | + except: | |
| 65 | + mtype = MimeType.objects.create( | |
| 66 | + typ = exercise_type, | |
| 67 | + icon = mime_type_to_material_icons[exercise_type] | |
| 68 | + ) | |
| 69 | + mtype.save() | |
| 70 | + self.object.exercise_type = mtype | |
| 71 | + except: | |
| 72 | + print('Exercise not uploaded') | |
| 73 | + | |
| 74 | + self.object.save() | |
| 75 | + #CREATE LOG | |
| 76 | + self.log_context['topic_id'] = topic.id | |
| 77 | + self.log_context['topic_name'] = topic.name | |
| 78 | + self.log_context['topic_slug'] = topic.slug | |
| 79 | + self.log_context['subject_id'] = topic.subject.id | |
| 80 | + self.log_context['subject_name'] = topic.subject.name | |
| 81 | + self.log_context['subject_slug'] = topic.subject.slug | |
| 82 | + | |
| 83 | + super(CreateExercise, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + #CREATE NOTIFICATION | |
| 88 | + super(CreateExercise, self).createNotification(message="uploaded a Exercise "+ self.object.name, actor=self.request.user, | |
| 89 | + resource_name=self.object.name, resource_link= reverse('course:view_topic', args=[self.object.topic.slug]), | |
| 90 | + users=self.object.topic.subject.students.all()) | |
| 91 | + | |
| 92 | + self.log_context['exercise_id'] = self.object.id | |
| 93 | + self.log_context['exercise_name'] = self.object.name | |
| 94 | + self.log_context['topic_id'] = self.object.topic.id | |
| 95 | + self.log_context['topic_name'] = self.object.topic.name | |
| 96 | + self.log_context['topic_slug'] = self.object.topic.slug | |
| 97 | + self.log_context['subject_id'] = self.object.topic.subject.id | |
| 98 | + self.log_context['subject_name'] = self.object.topic.subject.name | |
| 99 | + self.log_context['subject_slug'] = self.object.topic.subject.slug | |
| 100 | + self.log_context['course_id'] = self.object.topic.subject.course.id | |
| 101 | + self.log_context['course_name'] = self.object.topic.subject.course.name | |
| 102 | + self.log_context['course_slug'] = self.object.topic.subject.course.slug | |
| 103 | + self.log_context['course_category_id'] = self.object.topic.subject.course.category.id | |
| 104 | + self.log_context['course_category_name'] = self.object.topic.subject.course.category.name | |
| 105 | + | |
| 106 | + super(CreateExercise, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) | |
| 107 | + | |
| 108 | + return self.get_success_url() | |
| 109 | + | |
| 110 | + def get_context_data(self, **kwargs): | |
| 111 | + context = super(CreateExercise, self).get_context_data(**kwargs) | |
| 112 | + topic = get_object_or_404(Topic, slug=self.kwargs.get('slug')) | |
| 113 | + context['topic'] = topic | |
| 114 | + context['subject'] = topic.subject | |
| 115 | + context['subjects'] = topic.subject.course.subjects.all() | |
| 116 | + context['form'] = self.form_class | |
| 117 | + | |
| 118 | + try: | |
| 119 | + context['latest_exercise'] = Exercise.objects.latest('id') | |
| 120 | + except: | |
| 121 | + pass | |
| 122 | + return context | |
| 123 | + | |
| 124 | + def get_success_url(self): | |
| 125 | + self.success_url = redirect('course:exercise:render_exercise', id = self.object.id) | |
| 126 | + | |
| 127 | + return self.success_url | |
| 128 | + | |
| 129 | + | |
| 130 | +def render_exercise(request, id): | |
| 131 | + template_name = 'exercise/render_exercise.html' | |
| 132 | + exercise = get_object_or_404(Exercise, id = id) | |
| 133 | + | |
| 134 | + context = { | |
| 135 | + 'exercise': exercise | |
| 136 | + } | |
| 137 | + | |
| 138 | + log_context = {} | |
| 139 | + log_context['exercise_id'] = exercise.id | |
| 140 | + log_context['exercise_name'] = exercise.name | |
| 141 | + log_context['topic_id'] = exercise.topic.id | |
| 142 | + log_context['topic_name'] = exercise.topic.name | |
| 143 | + log_context['topic_slug'] = exercise.topic.slug | |
| 144 | + log_context['subject_id'] = exercise.topic.subject.id | |
| 145 | + log_context['subject_name'] = exercise.topic.subject.name | |
| 146 | + log_context['subject_slug'] = exercise.topic.subject.slug | |
| 147 | + log_context['course_id'] = exercise.topic.subject.course.id | |
| 148 | + log_context['course_name'] = exercise.topic.subject.course.name | |
| 149 | + log_context['course_slug'] = exercise.topic.subject.course.slug | |
| 150 | + log_context['course_category_id'] = exercise.topic.subject.course.category.id | |
| 151 | + log_context['course_category_name'] = exercise.topic.subject.course.category.name | |
| 152 | + | |
| 153 | + request.log_context = log_context | |
| 154 | + | |
| 155 | + return render(request, template_name, context) | |
| 156 | + | |
| 157 | + | |
| 158 | +class UpdateExercise(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.UpdateView): | |
| 159 | + log_component = 'exercise' | |
| 160 | + log_resource = 'exercise' | |
| 161 | + log_action = 'update' | |
| 162 | + log_context = {} | |
| 163 | + | |
| 164 | + allowed_roles = ['student'] | |
| 165 | + login_url = reverse_lazy("core:home") | |
| 166 | + redirect_field_name = 'next' | |
| 167 | + model = Exercise | |
| 168 | + template_name = 'exercise/update_exercise.html' | |
| 169 | + form_class = UpdateExerciseForm | |
| 170 | + context_object_name = 'exercise' | |
| 171 | + success_url = reverse_lazy('course:exercise:render_exercise') | |
| 172 | + | |
| 173 | + def form_invalid(self, form, **kwargs): | |
| 174 | + context = super(UpdateExercise, self).form_invalid(form) | |
| 175 | + context.status_code = 400 | |
| 176 | + | |
| 177 | + return context | |
| 178 | + | |
| 179 | + | |
| 180 | + def form_valid(self, form): | |
| 181 | + self.object = form.save() | |
| 182 | + | |
| 183 | + self.log_context['exercise_id'] = self.object.id | |
| 184 | + self.log_context['exercise_name'] = self.object.name | |
| 185 | + self.log_context['topic_id'] = self.object.topic.id | |
| 186 | + self.log_context['topic_name'] = self.object.topic.name | |
| 187 | + self.log_context['topic_slug'] = self.object.topic.slug | |
| 188 | + self.log_context['subject_id'] = self.object.topic.subject.id | |
| 189 | + self.log_context['subject_name'] = self.object.topic.subject.name | |
| 190 | + self.log_context['subject_slug'] = self.object.topic.subject.slug | |
| 191 | + self.log_context['course_id'] = self.object.topic.subject.course.id | |
| 192 | + self.log_context['course_name'] = self.object.topic.subject.course.name | |
| 193 | + self.log_context['course_slug'] = self.object.topic.subject.course.slug | |
| 194 | + self.log_context['course_category_id'] = self.object.topic.subject.course.category.id | |
| 195 | + self.log_context['course_category_name'] = self.object.topic.subject.course.category.name | |
| 196 | + | |
| 197 | + super(UpdateExercise, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) | |
| 198 | + | |
| 199 | + return super(UpdateExercise, self).form_valid(form) | |
| 200 | + | |
| 201 | + def get_object(self, queryset=None): | |
| 202 | + return get_object_or_404(Exercise, slug = self.kwargs.get('slug')) | |
| 203 | + | |
| 204 | + def get_success_url(self): | |
| 205 | + self.success_url = reverse_lazy('course:exercise:render_exercise', args = (self.object.id, )) | |
| 206 | + | |
| 207 | + return self.success_url | |
| 208 | + | |
| 209 | + | |
| 210 | +class DeleteExercise(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.DeleteView): | |
| 211 | + log_component = 'exercise' | |
| 212 | + log_resource = 'exercise' | |
| 213 | + log_action = 'delete' | |
| 214 | + log_context = {} | |
| 215 | + | |
| 216 | + allowed_roles = ['student'] | |
| 217 | + login_url = reverse_lazy("core:home") | |
| 218 | + redirect_field_name = 'next' | |
| 219 | + model = Exercise | |
| 220 | + template_name = 'exercise/delete_exercise.html' | |
| 221 | + | |
| 222 | + def dispatch(self, *args, **kwargs): | |
| 223 | + exercise = get_object_or_404(Exercise, slug = self.kwargs.get('slug')) | |
| 224 | + if(not (exercise.topic.owner == self.request.user) and not(has_role(self.request.user, 'system_admin')) ): | |
| 225 | + return self.handle_no_permission() | |
| 226 | + return super(DeleteExercise, self).dispatch(*args, **kwargs) | |
| 227 | + | |
| 228 | + def get_context_data(self, **kwargs): | |
| 229 | + context = super(DeleteExercise, self).get_context_data(**kwargs) | |
| 230 | + context['course'] = self.object.topic.subject.course | |
| 231 | + context['subject'] = self.object.topic.subject | |
| 232 | + context['exercise'] = self.object | |
| 233 | + context["topic"] = self.object.topic | |
| 234 | + return context | |
| 235 | + | |
| 236 | + def get_success_url(self): | |
| 237 | + self.log_context['exercise_id'] = self.object.id | |
| 238 | + self.log_context['exercise_name'] = self.object.name | |
| 239 | + self.log_context['topic_id'] = self.object.topic.id | |
| 240 | + self.log_context['topic_name'] = self.object.topic.name | |
| 241 | + self.log_context['topic_slug'] = self.object.topic.slug | |
| 242 | + self.log_context['subject_id'] = self.object.topic.subject.id | |
| 243 | + self.log_context['subject_name'] = self.object.topic.subject.name | |
| 244 | + self.log_context['subject_slug'] = self.object.topic.subject.slug | |
| 245 | + self.log_context['course_id'] = self.object.topic.subject.course.id | |
| 246 | + self.log_context['course_name'] = self.object.topic.subject.course.name | |
| 247 | + self.log_context['course_slug'] = self.object.topic.subject.course.slug | |
| 248 | + self.log_context['course_category_id'] = self.object.topic.subject.course.category.id | |
| 249 | + self.log_context['course_category_name'] = self.object.topic.subject.course.category.name | |
| 250 | + | |
| 251 | + super(DeleteExercise, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) | |
| 252 | + | |
| 253 | + return reverse_lazy('course:view_topic', kwargs={'slug' : self.object.topic.slug}) | |
| 0 | 254 | \ No newline at end of file | ... | ... |
files/migrations/0001_initial.py
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | -# Generated by Django 1.10 on 2016-11-13 17:47 | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 3 | 3 | from __future__ import unicode_literals |
| 4 | 4 | |
| 5 | -from django.conf import settings | |
| 6 | 5 | from django.db import migrations, models |
| 7 | 6 | import django.db.models.deletion |
| 8 | 7 | import files.models |
| ... | ... | @@ -15,7 +14,6 @@ class Migration(migrations.Migration): |
| 15 | 14 | dependencies = [ |
| 16 | 15 | ('courses', '0001_initial'), |
| 17 | 16 | ('core', '0001_initial'), |
| 18 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 19 | 17 | ] |
| 20 | 18 | |
| 21 | 19 | operations = [ |
| ... | ... | @@ -26,12 +24,11 @@ class Migration(migrations.Migration): |
| 26 | 24 | ('description', models.TextField(blank=True, verbose_name='Description')), |
| 27 | 25 | ('file_url', models.FileField(upload_to=files.models.file_path, verbose_name='File')), |
| 28 | 26 | ('file_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='topic_files', to='core.MimeType', verbose_name='Type file')), |
| 29 | - ('professor', models.ManyToManyField(related_name='file_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors')), | |
| 30 | 27 | ], |
| 31 | 28 | options={ |
| 29 | + 'ordering': ('-id',), | |
| 32 | 30 | 'verbose_name': 'File', |
| 33 | 31 | 'verbose_name_plural': 'Files', |
| 34 | - 'ordering': ('-id',), | |
| 35 | 32 | }, |
| 36 | 33 | bases=('courses.material',), |
| 37 | 34 | ), | ... | ... |
| ... | ... | @@ -0,0 +1,24 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 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 | + initial = True | |
| 12 | + | |
| 13 | + dependencies = [ | |
| 14 | + ('files', '0001_initial'), | |
| 15 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 16 | + ] | |
| 17 | + | |
| 18 | + operations = [ | |
| 19 | + migrations.AddField( | |
| 20 | + model_name='topicfile', | |
| 21 | + name='professor', | |
| 22 | + field=models.ManyToManyField(related_name='file_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors'), | |
| 23 | + ), | |
| 24 | + ] | ... | ... |
forum/migrations/0001_initial.py
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | -# Generated by Django 1.10 on 2016-11-13 17:47 | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 3 | 3 | from __future__ import unicode_literals |
| 4 | 4 | |
| 5 | -from django.conf import settings | |
| 6 | 5 | from django.db import migrations, models |
| 7 | 6 | import django.db.models.deletion |
| 8 | 7 | |
| ... | ... | @@ -13,7 +12,6 @@ class Migration(migrations.Migration): |
| 13 | 12 | |
| 14 | 13 | dependencies = [ |
| 15 | 14 | ('courses', '0001_initial'), |
| 16 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 17 | 15 | ] |
| 18 | 16 | |
| 19 | 17 | operations = [ |
| ... | ... | @@ -38,8 +36,6 @@ class Migration(migrations.Migration): |
| 38 | 36 | ('message', models.TextField(verbose_name='Post message')), |
| 39 | 37 | ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')), |
| 40 | 38 | ('post_date', models.DateTimeField(auto_now_add=True, verbose_name='Post Date')), |
| 41 | - ('forum', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Forum', verbose_name='Forum')), | |
| 42 | - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor')), | |
| 43 | 39 | ], |
| 44 | 40 | options={ |
| 45 | 41 | 'verbose_name': 'Post', |
| ... | ... | @@ -54,7 +50,6 @@ class Migration(migrations.Migration): |
| 54 | 50 | ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')), |
| 55 | 51 | ('answer_date', models.DateTimeField(auto_now_add=True, verbose_name='Answer Date')), |
| 56 | 52 | ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Post', verbose_name='Post')), |
| 57 | - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor')), | |
| 58 | 53 | ], |
| 59 | 54 | options={ |
| 60 | 55 | 'verbose_name': 'Post Answer', | ... | ... |
| ... | ... | @@ -0,0 +1,35 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 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 | + initial = True | |
| 13 | + | |
| 14 | + dependencies = [ | |
| 15 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 16 | + ('forum', '0001_initial'), | |
| 17 | + ] | |
| 18 | + | |
| 19 | + operations = [ | |
| 20 | + migrations.AddField( | |
| 21 | + model_name='postanswer', | |
| 22 | + name='user', | |
| 23 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor'), | |
| 24 | + ), | |
| 25 | + migrations.AddField( | |
| 26 | + model_name='post', | |
| 27 | + name='forum', | |
| 28 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Forum', verbose_name='Forum'), | |
| 29 | + ), | |
| 30 | + migrations.AddField( | |
| 31 | + model_name='post', | |
| 32 | + name='user', | |
| 33 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor'), | |
| 34 | + ), | |
| 35 | + ] | ... | ... |
links/migrations/0001_initial.py
poll/migrations/0001_initial.py
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | -# Generated by Django 1.10 on 2016-11-13 17:47 | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 3 | 3 | from __future__ import unicode_literals |
| 4 | 4 | |
| 5 | -from django.conf import settings | |
| 6 | 5 | from django.db import migrations, models |
| 7 | 6 | import django.db.models.deletion |
| 8 | 7 | |
| ... | ... | @@ -13,7 +12,6 @@ class Migration(migrations.Migration): |
| 13 | 12 | |
| 14 | 13 | dependencies = [ |
| 15 | 14 | ('courses', '0001_initial'), |
| 16 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 17 | 15 | ] |
| 18 | 16 | |
| 19 | 17 | operations = [ |
| ... | ... | @@ -25,9 +23,9 @@ class Migration(migrations.Migration): |
| 25 | 23 | ('order', models.PositiveSmallIntegerField(verbose_name='Order')), |
| 26 | 24 | ], |
| 27 | 25 | options={ |
| 26 | + 'ordering': ('order',), | |
| 28 | 27 | 'verbose_name': 'Answer', |
| 29 | 28 | 'verbose_name_plural': 'Answers', |
| 30 | - 'ordering': ('order',), | |
| 31 | 29 | }, |
| 32 | 30 | ), |
| 33 | 31 | migrations.CreateModel( |
| ... | ... | @@ -59,14 +57,4 @@ class Migration(migrations.Migration): |
| 59 | 57 | name='poll', |
| 60 | 58 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundet', to='poll.Poll', verbose_name='Poll'), |
| 61 | 59 | ), |
| 62 | - migrations.AddField( | |
| 63 | - model_name='answersstudent', | |
| 64 | - name='student', | |
| 65 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundent', to=settings.AUTH_USER_MODEL, verbose_name='Student'), | |
| 66 | - ), | |
| 67 | - migrations.AddField( | |
| 68 | - model_name='answer', | |
| 69 | - name='poll', | |
| 70 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='poll.Poll', verbose_name='Answers'), | |
| 71 | - ), | |
| 72 | 60 | ] | ... | ... |
| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 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 | + initial = True | |
| 13 | + | |
| 14 | + dependencies = [ | |
| 15 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 16 | + ('poll', '0001_initial'), | |
| 17 | + ] | |
| 18 | + | |
| 19 | + operations = [ | |
| 20 | + migrations.AddField( | |
| 21 | + model_name='answersstudent', | |
| 22 | + name='student', | |
| 23 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundent', to=settings.AUTH_USER_MODEL, verbose_name='Student'), | |
| 24 | + ), | |
| 25 | + migrations.AddField( | |
| 26 | + model_name='answer', | |
| 27 | + name='poll', | |
| 28 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='poll.Poll', verbose_name='Answers'), | |
| 29 | + ), | |
| 30 | + ] | ... | ... |
users/migrations/0001_initial.py
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | -# Generated by Django 1.10 on 2016-11-13 17:42 | |
| 2 | +# Generated by Django 1.10 on 2016-11-14 04:44 | |
| 3 | 3 | from __future__ import unicode_literals |
| 4 | 4 | |
| 5 | 5 | import django.contrib.auth.models |
| ... | ... | @@ -46,8 +46,8 @@ class Migration(migrations.Migration): |
| 46 | 46 | ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), |
| 47 | 47 | ], |
| 48 | 48 | options={ |
| 49 | - 'verbose_name_plural': 'Users', | |
| 50 | 49 | 'verbose_name': 'User', |
| 50 | + 'verbose_name_plural': 'Users', | |
| 51 | 51 | }, |
| 52 | 52 | managers=[ |
| 53 | 53 | ('objects', django.contrib.auth.models.UserManager()), | ... | ... |