Commit e1767fc3dbe78e9cec60bce157ccc71935c143cd
1 parent
8efbd63d
Exists in
master
and in
5 other branches
subject category #62
Showing
35 changed files
with
671 additions
and
563 deletions
Show diff stats
core/admin.py
| 1 | 1 | from django.contrib import admin |
| 2 | 2 | |
| 3 | -from .models import Action, Resource, Action_Resource, Log | |
| 3 | +from .models import Action, Resource, Action_Resource, Log, MymeType | |
| 4 | 4 | |
| 5 | 5 | class ActionAdmin(admin.ModelAdmin): |
| 6 | 6 | list_display = ['name', 'created_date'] |
| ... | ... | @@ -18,7 +18,12 @@ class LogAdmin(admin.ModelAdmin): |
| 18 | 18 | list_display = ['datetime', 'user', 'action_resource'] |
| 19 | 19 | search_fields = ['user'] |
| 20 | 20 | |
| 21 | +class MymeTypeAdmin(admin.ModelAdmin): | |
| 22 | + list_display = ['typ', 'icon'] | |
| 23 | + search_fields = ['typ', 'icon'] | |
| 24 | + | |
| 21 | 25 | admin.site.register(Action, ActionAdmin) |
| 22 | 26 | admin.site.register(Resource, ResourceAdmin) |
| 23 | 27 | admin.site.register(Action_Resource, ActionResourceAdmin) |
| 24 | -admin.site.register(Log, LogAdmin) | |
| 25 | 28 | \ No newline at end of file |
| 29 | +admin.site.register(Log, LogAdmin) | |
| 30 | +admin.site.register(MymeType, MymeTypeAdmin) | |
| 26 | 31 | \ No newline at end of file | ... | ... |
core/migrations/0001_initial.py
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | -# Generated by Django 1.10 on 2016-10-05 13:37 | |
| 2 | +# Generated by Django 1.10 on 2016-10-17 15:49 | |
| 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 | |
| ... | ... | @@ -13,7 +12,6 @@ class Migration(migrations.Migration): |
| 13 | 12 | initial = True |
| 14 | 13 | |
| 15 | 14 | dependencies = [ |
| 16 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 17 | 15 | ] |
| 18 | 16 | |
| 19 | 17 | operations = [ |
| ... | ... | @@ -25,19 +23,18 @@ class Migration(migrations.Migration): |
| 25 | 23 | ('created_date', models.DateField(auto_now_add=True, verbose_name='Created Date')), |
| 26 | 24 | ], |
| 27 | 25 | options={ |
| 28 | - 'verbose_name': 'Action', | |
| 29 | 26 | 'verbose_name_plural': 'Actions', |
| 27 | + 'verbose_name': 'Action', | |
| 30 | 28 | }, |
| 31 | 29 | ), |
| 32 | 30 | migrations.CreateModel( |
| 33 | 31 | name='Action_Resource', |
| 34 | 32 | fields=[ |
| 35 | 33 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
| 36 | - ('action', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action', verbose_name='Action_Applied')), | |
| 37 | 34 | ], |
| 38 | 35 | options={ |
| 39 | - 'verbose_name': 'Action_Resource', | |
| 40 | 36 | 'verbose_name_plural': 'Action_Resources', |
| 37 | + 'verbose_name': 'Action_Resource', | |
| 41 | 38 | }, |
| 42 | 39 | ), |
| 43 | 40 | migrations.CreateModel( |
| ... | ... | @@ -45,12 +42,22 @@ class Migration(migrations.Migration): |
| 45 | 42 | fields=[ |
| 46 | 43 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
| 47 | 44 | ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')), |
| 48 | - ('action_resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource')), | |
| 49 | - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Actor')), | |
| 50 | 45 | ], |
| 51 | 46 | options={ |
| 52 | - 'verbose_name': 'Log', | |
| 53 | 47 | 'verbose_name_plural': 'Logs', |
| 48 | + 'verbose_name': 'Log', | |
| 49 | + }, | |
| 50 | + ), | |
| 51 | + migrations.CreateModel( | |
| 52 | + name='MymeType', | |
| 53 | + fields=[ | |
| 54 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
| 55 | + ('typ', models.CharField(max_length=100, unique=True, verbose_name='Type')), | |
| 56 | + ('icon', models.CharField(max_length=50, unique=True, verbose_name='Icon')), | |
| 57 | + ], | |
| 58 | + options={ | |
| 59 | + 'verbose_name_plural': 'Amadeus Myme Types', | |
| 60 | + 'verbose_name': 'Amadeus Myme Type', | |
| 54 | 61 | }, |
| 55 | 62 | ), |
| 56 | 63 | migrations.CreateModel( |
| ... | ... | @@ -61,12 +68,10 @@ class Migration(migrations.Migration): |
| 61 | 68 | ('read', models.BooleanField(default=False, verbose_name='Read')), |
| 62 | 69 | ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')), |
| 63 | 70 | ('action_resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource')), |
| 64 | - ('actor', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notification_Performer', to=settings.AUTH_USER_MODEL, verbose_name='Perfomer')), | |
| 65 | - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notification_Actor', to=settings.AUTH_USER_MODEL, verbose_name='User')), | |
| 66 | 71 | ], |
| 67 | 72 | options={ |
| 68 | - 'verbose_name': 'Notification', | |
| 69 | 73 | 'verbose_name_plural': 'Notifications', |
| 74 | + 'verbose_name': 'Notification', | |
| 70 | 75 | }, |
| 71 | 76 | ), |
| 72 | 77 | migrations.CreateModel( |
| ... | ... | @@ -79,13 +84,8 @@ class Migration(migrations.Migration): |
| 79 | 84 | ('url', models.CharField(default='', max_length=100, verbose_name='URL')), |
| 80 | 85 | ], |
| 81 | 86 | options={ |
| 82 | - 'verbose_name': 'Resource', | |
| 83 | 87 | 'verbose_name_plural': 'Resources', |
| 88 | + 'verbose_name': 'Resource', | |
| 84 | 89 | }, |
| 85 | 90 | ), |
| 86 | - migrations.AddField( | |
| 87 | - model_name='action_resource', | |
| 88 | - name='resource', | |
| 89 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Resource', verbose_name='Resource'), | |
| 90 | - ), | |
| 91 | 91 | ] | ... | ... |
| ... | ... | @@ -0,0 +1,50 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2016-10-17 15:49 | |
| 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 | + ('core', '0001_initial'), | |
| 16 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 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 | + ] | ... | ... |
core/migrations/0002_mymetype.py
| ... | ... | @@ -1,27 +0,0 @@ |
| 1 | -# -*- coding: utf-8 -*- | |
| 2 | -# Generated by Django 1.10 on 2016-10-12 17:29 | |
| 3 | -from __future__ import unicode_literals | |
| 4 | - | |
| 5 | -from django.db import migrations, models | |
| 6 | - | |
| 7 | - | |
| 8 | -class Migration(migrations.Migration): | |
| 9 | - | |
| 10 | - dependencies = [ | |
| 11 | - ('core', '0001_initial'), | |
| 12 | - ] | |
| 13 | - | |
| 14 | - operations = [ | |
| 15 | - migrations.CreateModel( | |
| 16 | - name='MymeType', | |
| 17 | - fields=[ | |
| 18 | - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
| 19 | - ('typ', models.CharField(max_length=100, unique=True, verbose_name='Type')), | |
| 20 | - ('icon', models.CharField(max_length=50, unique=True, verbose_name='Icon')), | |
| 21 | - ], | |
| 22 | - options={ | |
| 23 | - 'verbose_name_plural': 'Amadeus Myme Types', | |
| 24 | - 'verbose_name': 'Amadeus Myme Type', | |
| 25 | - }, | |
| 26 | - ), | |
| 27 | - ] |
courses/admin.py
| 1 | 1 | from django.contrib import admin |
| 2 | 2 | |
| 3 | -from .models import CourseCategory, Course, Subject,Topic, Activity, Material | |
| 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'] |
| 7 | 7 | search_fields = ['name', 'slug'] |
| 8 | 8 | |
| 9 | +class CategorySubjectAdmin(admin.ModelAdmin): | |
| 10 | + list_display = ['name', 'slug'] | |
| 11 | + search_fields = ['name', 'slug'] | |
| 12 | + | |
| 9 | 13 | class CourseAdmin(admin.ModelAdmin): |
| 10 | 14 | list_display = ['name', 'slug'] |
| 11 | 15 | search_fields = ['name', 'slug'] |
| ... | ... | @@ -32,3 +36,4 @@ admin.site.register(Subject, SubjectAdmin) |
| 32 | 36 | admin.site.register(Topic, TopicAdmin) |
| 33 | 37 | admin.site.register(Activity,ActivityAdmin) |
| 34 | 38 | admin.site.register(Material,MaterialAdmin) |
| 39 | +admin.site.register(CategorySubject, CategorySubjectAdmin) | ... | ... |
courses/forms.py
| ... | ... | @@ -192,7 +192,7 @@ class ActivityForm(forms.ModelForm): |
| 192 | 192 | class FileMaterialForm(forms.ModelForm): |
| 193 | 193 | class Meta: |
| 194 | 194 | model = FileMaterial |
| 195 | - fields = ['material', 'file', 'name'] | |
| 195 | + fields = ['name', 'file'] | |
| 196 | 196 | |
| 197 | 197 | class LinkMaterialForm(forms.ModelForm): |
| 198 | 198 | class Meta: | ... | ... |
courses/migrations/0001_initial.py
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | -# Generated by Django 1.10 on 2016-10-05 13:37 | |
| 2 | +# Generated by Django 1.10 on 2016-10-17 15:49 | |
| 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 |
| ... | ... | @@ -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 | ('core', '0001_initial'), |
| 19 | 17 | ] |
| 20 | 18 | |
| ... | ... | @@ -23,9 +21,8 @@ class Migration(migrations.Migration): |
| 23 | 21 | name='Activity', |
| 24 | 22 | fields=[ |
| 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 | - ('limit_date', models.DateTimeField(verbose_name='Deliver Date')), | |
| 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,15 +32,14 @@ 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 | - 'verbose_name': 'Activity File', | |
| 42 | 37 | 'verbose_name_plural': 'Activitys Files', |
| 38 | + 'verbose_name': 'Activity File', | |
| 43 | 39 | }, |
| 44 | 40 | ), |
| 45 | 41 | migrations.CreateModel( |
| 46 | - name='Category', | |
| 42 | + name='CategorySubject', | |
| 47 | 43 | fields=[ |
| 48 | 44 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
| 49 | 45 | ('name', models.CharField(max_length=100, unique=True, verbose_name='Name')), |
| ... | ... | @@ -51,8 +47,8 @@ class Migration(migrations.Migration): |
| 51 | 47 | ('create_date', models.DateField(auto_now_add=True, verbose_name='Creation Date')), |
| 52 | 48 | ], |
| 53 | 49 | options={ |
| 54 | - 'verbose_name': 'Category', | |
| 55 | 50 | 'verbose_name_plural': 'Categories', |
| 51 | + 'verbose_name': 'Category', | |
| 56 | 52 | }, |
| 57 | 53 | ), |
| 58 | 54 | migrations.CreateModel( |
| ... | ... | @@ -70,22 +66,48 @@ class Migration(migrations.Migration): |
| 70 | 66 | ('init_date', models.DateField(verbose_name='Begin of Course Date')), |
| 71 | 67 | ('end_date', models.DateField(verbose_name='End of Course Date')), |
| 72 | 68 | ('image', models.ImageField(blank=True, upload_to='courses/', verbose_name='Image')), |
| 73 | - ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Category', verbose_name='Category')), | |
| 74 | - ('professors', models.ManyToManyField(related_name='courses_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors')), | |
| 75 | - ('students', models.ManyToManyField(related_name='courses_student', to=settings.AUTH_USER_MODEL, verbose_name='Students')), | |
| 76 | 69 | ], |
| 77 | 70 | options={ |
| 78 | - 'verbose_name': 'Course', | |
| 79 | 71 | 'ordering': ('create_date', 'name'), |
| 80 | 72 | 'verbose_name_plural': 'Courses', |
| 73 | + 'verbose_name': 'Course', | |
| 81 | 74 | }, |
| 82 | 75 | ), |
| 83 | 76 | migrations.CreateModel( |
| 77 | + name='CourseCategory', | |
| 78 | + fields=[ | |
| 79 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
| 80 | + ('name', models.CharField(max_length=100, unique=True, verbose_name='Name')), | |
| 81 | + ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True, verbose_name='Slug')), | |
| 82 | + ('create_date', models.DateField(auto_now_add=True, verbose_name='Creation Date')), | |
| 83 | + ], | |
| 84 | + options={ | |
| 85 | + 'verbose_name_plural': 'Categories', | |
| 86 | + 'verbose_name': 'Category', | |
| 87 | + }, | |
| 88 | + ), | |
| 89 | + migrations.CreateModel( | |
| 90 | + name='FileMaterial', | |
| 91 | + fields=[ | |
| 92 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
| 93 | + ('file', models.FileField(upload_to='uploads/%Y/%m/%d')), | |
| 94 | + ('name', models.CharField(max_length=100)), | |
| 95 | + ], | |
| 96 | + ), | |
| 97 | + migrations.CreateModel( | |
| 98 | + name='LinkMaterial', | |
| 99 | + fields=[ | |
| 100 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
| 101 | + ('name', models.CharField(max_length=100)), | |
| 102 | + ('description', models.TextField()), | |
| 103 | + ('url', models.URLField(max_length=300, verbose_name='Link')), | |
| 104 | + ], | |
| 105 | + ), | |
| 106 | + migrations.CreateModel( | |
| 84 | 107 | name='Material', |
| 85 | 108 | fields=[ |
| 86 | 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')), |
| 87 | 110 | ('all_students', models.BooleanField(default=False, verbose_name='All Students')), |
| 88 | - ('students', models.ManyToManyField(related_name='materials', to=settings.AUTH_USER_MODEL, verbose_name='Students')), | |
| 89 | 111 | ], |
| 90 | 112 | bases=('core.resource',), |
| 91 | 113 | ), |
| ... | ... | @@ -101,13 +123,11 @@ class Migration(migrations.Migration): |
| 101 | 123 | ('end_date', models.DateField(verbose_name='End of Subject Date')), |
| 102 | 124 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), |
| 103 | 125 | ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), |
| 104 | - ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subjects', to='courses.Course', verbose_name='Course')), | |
| 105 | - ('professors', models.ManyToManyField(related_name='subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors')), | |
| 106 | 126 | ], |
| 107 | 127 | options={ |
| 108 | - 'verbose_name': 'Subject', | |
| 109 | 128 | 'ordering': ('create_date', 'name'), |
| 110 | 129 | 'verbose_name_plural': 'Subjects', |
| 130 | + 'verbose_name': 'Subject', | |
| 111 | 131 | }, |
| 112 | 132 | ), |
| 113 | 133 | migrations.CreateModel( |
| ... | ... | @@ -117,11 +137,10 @@ class Migration(migrations.Migration): |
| 117 | 137 | ('name', models.CharField(max_length=100, verbose_name='Name')), |
| 118 | 138 | ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True, verbose_name='Slug')), |
| 119 | 139 | ('description', models.TextField(blank=True, verbose_name='Description')), |
| 120 | - ('subjects', models.ManyToManyField(to='courses.Subject')), | |
| 121 | 140 | ], |
| 122 | 141 | options={ |
| 123 | - 'verbose_name': 'subject category', | |
| 124 | 142 | 'verbose_name_plural': 'subject categories', |
| 143 | + 'verbose_name': 'subject category', | |
| 125 | 144 | }, |
| 126 | 145 | ), |
| 127 | 146 | migrations.CreateModel( |
| ... | ... | @@ -134,23 +153,11 @@ class Migration(migrations.Migration): |
| 134 | 153 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), |
| 135 | 154 | ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), |
| 136 | 155 | ('visible', models.BooleanField(default=False, verbose_name='Visible')), |
| 137 | - ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Owner')), | |
| 138 | - ('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Subject', verbose_name='Subject')), | |
| 139 | 156 | ], |
| 140 | 157 | options={ |
| 141 | - 'verbose_name': 'Topic', | |
| 142 | 158 | 'ordering': ('create_date', 'name'), |
| 143 | 159 | 'verbose_name_plural': 'Topics', |
| 160 | + 'verbose_name': 'Topic', | |
| 144 | 161 | }, |
| 145 | 162 | ), |
| 146 | - migrations.AddField( | |
| 147 | - model_name='material', | |
| 148 | - name='topic', | |
| 149 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='courses.Topic', verbose_name='Topic'), | |
| 150 | - ), | |
| 151 | - migrations.AddField( | |
| 152 | - model_name='activity', | |
| 153 | - name='topic', | |
| 154 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='courses.Topic', verbose_name='Topic'), | |
| 155 | - ), | |
| 156 | 163 | ] | ... | ... |
| ... | ... | @@ -0,0 +1,105 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2016-10-17 15:49 | |
| 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 | + ('courses', '0001_initial'), | |
| 16 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 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(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='professors', | |
| 83 | + field=models.ManyToManyField(related_name='courses_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors'), | |
| 84 | + ), | |
| 85 | + migrations.AddField( | |
| 86 | + model_name='course', | |
| 87 | + name='students', | |
| 88 | + field=models.ManyToManyField(related_name='courses_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
| 89 | + ), | |
| 90 | + migrations.AddField( | |
| 91 | + model_name='activityfile', | |
| 92 | + name='diet', | |
| 93 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='courses.Activity'), | |
| 94 | + ), | |
| 95 | + migrations.AddField( | |
| 96 | + model_name='activity', | |
| 97 | + name='students', | |
| 98 | + field=models.ManyToManyField(related_name='activities', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
| 99 | + ), | |
| 100 | + migrations.AddField( | |
| 101 | + model_name='activity', | |
| 102 | + name='topic', | |
| 103 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='courses.Topic', verbose_name='Topic'), | |
| 104 | + ), | |
| 105 | + ] | ... | ... |
courses/migrations/0002_subject_students.py
| ... | ... | @@ -1,22 +0,0 @@ |
| 1 | -# -*- coding: utf-8 -*- | |
| 2 | -# Generated by Django 1.10 on 2016-10-05 21:02 | |
| 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 | - ('courses', '0001_initial'), | |
| 14 | - ] | |
| 15 | - | |
| 16 | - operations = [ | |
| 17 | - migrations.AddField( | |
| 18 | - model_name='subject', | |
| 19 | - name='students', | |
| 20 | - field=models.ManyToManyField(related_name='subject_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
| 21 | - ), | |
| 22 | - ] |
courses/migrations/0003_auto_20161007_1612.py
| ... | ... | @@ -1,30 +0,0 @@ |
| 1 | -# -*- coding: utf-8 -*- | |
| 2 | -# Generated by Django 1.10 on 2016-10-07 19:12 | |
| 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 | - ('courses', '0002_subject_students'), | |
| 13 | - ] | |
| 14 | - | |
| 15 | - operations = [ | |
| 16 | - migrations.RenameModel( | |
| 17 | - old_name='Category', | |
| 18 | - new_name='CourseCategory', | |
| 19 | - ), | |
| 20 | - migrations.AlterField( | |
| 21 | - model_name='activity', | |
| 22 | - name='limit_date', | |
| 23 | - field=models.DateField(verbose_name='Deliver Date'), | |
| 24 | - ), | |
| 25 | - migrations.AlterField( | |
| 26 | - model_name='subject', | |
| 27 | - name='professors', | |
| 28 | - field=models.ManyToManyField(related_name='professors_subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors'), | |
| 29 | - ), | |
| 30 | - ] |
courses/migrations/0004_auto_20161011_1951.py
| ... | ... | @@ -1,21 +0,0 @@ |
| 1 | -# -*- coding: utf-8 -*- | |
| 2 | -# Generated by Django 1.10 on 2016-10-11 22:51 | |
| 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', '0003_auto_20161007_1612'), | |
| 13 | - ] | |
| 14 | - | |
| 15 | - operations = [ | |
| 16 | - migrations.AlterField( | |
| 17 | - model_name='course', | |
| 18 | - name='category', | |
| 19 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='course_category', to='courses.CourseCategory', verbose_name='Category'), | |
| 20 | - ), | |
| 21 | - ] |
courses/migrations/0005_file.py
| ... | ... | @@ -1,31 +0,0 @@ |
| 1 | -# -*- coding: utf-8 -*- | |
| 2 | -# Generated by Django 1.10 on 2016-10-13 17:29 | |
| 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 | - ('core', '0002_mymetype'), | |
| 13 | - ('courses', '0004_auto_20161011_1951'), | |
| 14 | - ] | |
| 15 | - | |
| 16 | - operations = [ | |
| 17 | - migrations.CreateModel( | |
| 18 | - name='File', | |
| 19 | - fields=[ | |
| 20 | - ('material_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Material')), | |
| 21 | - ('description', models.TextField(blank=True, verbose_name='Description')), | |
| 22 | - ('content', models.FileField(upload_to='uploads/courses/subject/topic/%Y/%m/%d/')), | |
| 23 | - ('typ', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='file', to='core.MymeType', verbose_name='Type')), | |
| 24 | - ], | |
| 25 | - options={ | |
| 26 | - 'verbose_name': 'Topic file', | |
| 27 | - 'verbose_name_plural': 'Topic files', | |
| 28 | - }, | |
| 29 | - bases=('courses.material',), | |
| 30 | - ), | |
| 31 | - ] |
courses/migrations/0006_auto_20161017_0117.py
| ... | ... | @@ -1,27 +0,0 @@ |
| 1 | -# -*- coding: utf-8 -*- | |
| 2 | -# Generated by Django 1.10 on 2016-10-17 04:17 | |
| 3 | -from __future__ import unicode_literals | |
| 4 | - | |
| 5 | -from django.db import migrations | |
| 6 | - | |
| 7 | - | |
| 8 | -class Migration(migrations.Migration): | |
| 9 | - | |
| 10 | - dependencies = [ | |
| 11 | - ('core', '0002_mymetype'), | |
| 12 | - ('courses', '0005_file'), | |
| 13 | - ] | |
| 14 | - | |
| 15 | - operations = [ | |
| 16 | - migrations.RemoveField( | |
| 17 | - model_name='file', | |
| 18 | - name='material_ptr', | |
| 19 | - ), | |
| 20 | - migrations.RemoveField( | |
| 21 | - model_name='file', | |
| 22 | - name='typ', | |
| 23 | - ), | |
| 24 | - migrations.DeleteModel( | |
| 25 | - name='File', | |
| 26 | - ), | |
| 27 | - ] |
courses/migrations/0007_filematerial_linkmaterial.py
| ... | ... | @@ -1,35 +0,0 @@ |
| 1 | -# -*- coding: utf-8 -*- | |
| 2 | -# Generated by Django 1.10 on 2016-10-17 04:55 | |
| 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', '0006_auto_20161017_0117'), | |
| 13 | - ] | |
| 14 | - | |
| 15 | - operations = [ | |
| 16 | - migrations.CreateModel( | |
| 17 | - name='FileMaterial', | |
| 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 | - ('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_file', to='courses.Material', verbose_name='Material')), | |
| 23 | - ], | |
| 24 | - ), | |
| 25 | - migrations.CreateModel( | |
| 26 | - name='LinkMaterial', | |
| 27 | - fields=[ | |
| 28 | - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
| 29 | - ('name', models.CharField(max_length=100)), | |
| 30 | - ('description', models.TextField()), | |
| 31 | - ('url', models.URLField(max_length=300, verbose_name='Link')), | |
| 32 | - ('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_link', to='courses.Material', verbose_name='Material')), | |
| 33 | - ], | |
| 34 | - ), | |
| 35 | - ] |
courses/models.py
| ... | ... | @@ -18,6 +18,18 @@ class CourseCategory(models.Model): |
| 18 | 18 | def __str__(self): |
| 19 | 19 | return self.name |
| 20 | 20 | |
| 21 | +class CategorySubject(models.Model): | |
| 22 | + name = models.CharField(_('Name'), max_length=100, unique=True) | |
| 23 | + slug = AutoSlugField(_("Slug"), populate_from='name', unique=True) | |
| 24 | + create_date = models.DateField(_('Creation Date'), auto_now_add=True) | |
| 25 | + | |
| 26 | + class Meta: | |
| 27 | + verbose_name = _('Category') | |
| 28 | + verbose_name_plural = _('Categories') | |
| 29 | + | |
| 30 | + def __str__(self): | |
| 31 | + return self.name | |
| 32 | + | |
| 21 | 33 | class Course(models.Model): |
| 22 | 34 | |
| 23 | 35 | name = models.CharField(_('Name'), max_length = 100) |
| ... | ... | @@ -54,6 +66,7 @@ class Subject(models.Model): |
| 54 | 66 | create_date = models.DateTimeField(_('Creation Date'), auto_now_add = True) |
| 55 | 67 | update_date = models.DateTimeField(_('Date of last update'), auto_now=True) |
| 56 | 68 | course = models.ForeignKey(Course, verbose_name = _('Course'), related_name="subjects") |
| 69 | + category = models.ForeignKey(CategorySubject, verbose_name = _('Category'), related_name='subject_category',null=True) | |
| 57 | 70 | professors = models.ManyToManyField(User,verbose_name=_('Professors'), related_name='professors_subjects') |
| 58 | 71 | students = models.ManyToManyField(User,verbose_name=_('Students'), related_name='subject_student') |
| 59 | 72 | ... | ... |
| ... | ... | @@ -0,0 +1,82 @@ |
| 1 | +function getCookie(name) { | |
| 2 | + var cookieValue = null; | |
| 3 | + if (document.cookie && document.cookie !== '') { | |
| 4 | + var cookies = document.cookie.split(';'); | |
| 5 | + for (var i = 0; i < cookies.length; i++) { | |
| 6 | + var cookie = jQuery.trim(cookies[i]); | |
| 7 | + // Does this cookie string begin with the name we want? | |
| 8 | + if (cookie.substring(0, name.length + 1) === (name + '=')) { | |
| 9 | + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); | |
| 10 | + break; | |
| 11 | + } | |
| 12 | + } | |
| 13 | + } | |
| 14 | + return cookieValue; | |
| 15 | +} | |
| 16 | + | |
| 17 | + | |
| 18 | +function createMaterial(url, topic) { | |
| 19 | + $.ajax({ | |
| 20 | + url: url, | |
| 21 | + data: {'topic': topic}, | |
| 22 | + success: function(data) { | |
| 23 | + $(".material_form").html(data); | |
| 24 | + $("#id_topic").val(topic); | |
| 25 | + | |
| 26 | + setMaterialCreateFormSubmit(); | |
| 27 | + } | |
| 28 | + }); | |
| 29 | + | |
| 30 | + $("#editFileModal").modal(); | |
| 31 | +} | |
| 32 | + | |
| 33 | +function setMaterialCreateFormSubmit() { | |
| 34 | + | |
| 35 | + var frm = $('#material_create'); | |
| 36 | + frm.submit(function () { | |
| 37 | + $.ajax({ | |
| 38 | + type: frm.attr('method'), | |
| 39 | + url: frm.attr('action'), | |
| 40 | + data: frm.serialize(), | |
| 41 | + success: function (data) { | |
| 42 | + data = data.split('-'); | |
| 43 | + | |
| 44 | + $('.foruns_list').append("<li><i class='fa fa-commenting' aria-hidden='true'></i> <a id='forum_"+data[1]+"' href='"+data[0]+"'> "+data[2]+"</a></li>"); | |
| 45 | + | |
| 46 | + $("#createForum").modal('hide'); | |
| 47 | + | |
| 48 | + showForum(data[0], data[1]); | |
| 49 | + }, | |
| 50 | + error: function(data) { | |
| 51 | + $(".forum_form").html(data.responseText); | |
| 52 | + setMaterialCreateFormSubmit(); | |
| 53 | + } | |
| 54 | + }); | |
| 55 | + return false; | |
| 56 | + }); | |
| 57 | +} | |
| 58 | + | |
| 59 | +function setMaterialUpdateFormSubmit(success_message) { | |
| 60 | + | |
| 61 | + var frm = $('#material_create'); | |
| 62 | + frm.submit(function () { | |
| 63 | + $.ajax({ | |
| 64 | + type: frm.attr('method'), | |
| 65 | + url: frm.attr('action'), | |
| 66 | + data: frm.serialize(), | |
| 67 | + success: function (data) { | |
| 68 | + $('.forum_view').html(data); | |
| 69 | + | |
| 70 | + alertify.success(success_message); | |
| 71 | + | |
| 72 | + $("#editForum").modal('hide'); | |
| 73 | + }, | |
| 74 | + error: function(data) { | |
| 75 | + $(".forum_form").html(data.responseText); | |
| 76 | + | |
| 77 | + setMaterialUpdateFormSubmit(success_message); | |
| 78 | + } | |
| 79 | + }); | |
| 80 | + return false; | |
| 81 | + }); | |
| 82 | +} | |
| 0 | 83 | \ No newline at end of file | ... | ... |
courses/templates/course/view.html
| ... | ... | @@ -48,7 +48,14 @@ |
| 48 | 48 | {% endblock %} |
| 49 | 49 | |
| 50 | 50 | {% block content %} |
| 51 | - | |
| 51 | +<div class="col-md-12"> | |
| 52 | + <div class="btn-group btn-group-justified btn-group-raised"> | |
| 53 | + <a href="?category=all" class="btn btn-raised btn-info">Todos</a> | |
| 54 | + {% for category_subject in categorys_subjects %} | |
| 55 | + <a href="?category={{category_subject.name}}" class="btn btn-raised btn-primary">{{category_subject.name}}</a> | |
| 56 | + {% endfor %} | |
| 57 | + </div> | |
| 58 | +</div> | |
| 52 | 59 | <div class="col-md-12"> |
| 53 | 60 | <div class="panel panel-info"> |
| 54 | 61 | <div class="panel-heading headingOne"> |
| ... | ... | @@ -157,7 +164,9 @@ |
| 157 | 164 | </div> |
| 158 | 165 | |
| 159 | 166 | <div class="panel-group ui-accordion ui-widget ui-helper-reset ui-sortable" id="accordion" role="tablist" aria-multiselectable="false"> |
| 160 | - <div><div class="panel panel-info"> | |
| 167 | + <div> | |
| 168 | + | |
| 169 | + <div class="panel panel-info"> | |
| 161 | 170 | </div> |
| 162 | 171 | |
| 163 | 172 | |
| ... | ... | @@ -182,60 +191,105 @@ |
| 182 | 191 | </div> |
| 183 | 192 | </div> |
| 184 | 193 | <div> |
| 185 | - | |
| 186 | -{% for subject in subjects %} | |
| 187 | -<div class="panel panel-info"> | |
| 188 | - <div class="panel-heading headingTwo ui-sortable-handle" role="tab"> | |
| 189 | - <div class="row"> | |
| 190 | - <div class="col-xs-9 col-md-10 titleTopic"> | |
| 191 | - <a role="button" data-toggle="collapse" data-parent="#accordion" href=".collapseTwo" aria-expanded="true" aria-controls="collapseTwo"> | |
| 192 | - <h4 style="color:white">{{subject.name}}</h4> | |
| 193 | - </a> | |
| 194 | - </div> | |
| 195 | - <div class="col-xs-3 col-md-2" id="divMoreActions"> | |
| 196 | - <div class="btn-group"> | |
| 197 | - <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | |
| 198 | - <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i> | |
| 199 | - </button> | |
| 200 | - <ul class="dropdown-menu" aria-labelledby="moreActions"> | |
| 201 | - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal3"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i> Replicate</a></li> | |
| 202 | - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#removeSubject2"><i class="fa fa-trash fa-fw" aria-hidden="true"></i> Remove</a></li> | |
| 203 | - </ul> | |
| 194 | + {% if request.GET.category == 'all' or none or request.GET.category == '' %} | |
| 195 | + {% for subject in subjects %} | |
| 196 | + <div class="panel panel-info"> | |
| 197 | + <div class="panel-heading headingTwo ui-sortable-handle" role="tab"> | |
| 198 | + <div class="row"> | |
| 199 | + <div class="col-xs-9 col-md-10 titleTopic"> | |
| 200 | + <a role="button" data-toggle="collapse" data-parent="#accordion" href=".collapseTwo" aria-expanded="true" aria-controls="collapseTwo"> | |
| 201 | + <h4 style="color:white">{{subject.name}}</h4> | |
| 202 | + </a> | |
| 203 | + </div> | |
| 204 | + <div class="col-xs-3 col-md-2" id="divMoreActions"> | |
| 205 | + <div class="btn-group"> | |
| 206 | + <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | |
| 207 | + <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i> | |
| 208 | + </button> | |
| 209 | + <ul class="dropdown-menu" aria-labelledby="moreActions"> | |
| 210 | + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal3"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i> Replicate</a></li> | |
| 211 | + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#removeSubject2"><i class="fa fa-trash fa-fw" aria-hidden="true"></i> Remove</a></li> | |
| 212 | + </ul> | |
| 213 | + </div> | |
| 214 | + </div> | |
| 215 | + </div> | |
| 204 | 216 | </div> |
| 217 | + <div class="panel-body"> | |
| 218 | + <p><b>{% trans "Professor" %}: </b>{% for professor in subject.professors.all %}{% if not forloop.first %},{% endif %} | |
| 219 | + {{professor}}{% if forloop.last %}.{% endif %}{% endfor %}</p> | |
| 220 | + <p> | |
| 221 | + <b>{% trans "Description" %}: </b> | |
| 222 | + <i> | |
| 223 | + {{subject.description}} | |
| 224 | + </i> | |
| 225 | + </p> | |
| 226 | + <div class="row"> | |
| 227 | + <div class="col-xs-6 col-md-6"> | |
| 228 | + <p><b>{% trans "Begining" %}: </b>{{subject.init_date}}</p> | |
| 229 | + </div> | |
| 230 | + <div class="col-xs-6 col-md-6"> | |
| 231 | + <p><b>{% trans "End" %}: </b>{{subject.end_date}}</p> | |
| 232 | + </div> | |
| 233 | + </div> | |
| 234 | + <a href="{% url 'course:view_subject' subject.slug %}" class="btn btn-raised btn-default center-block">{% trans 'View Subject' %}<div class="ripple-container"></div></a> | |
| 235 | + </div> | |
| 205 | 236 | </div> |
| 206 | - </div> | |
| 207 | - </div> | |
| 208 | - <div class="panel-body"> | |
| 209 | - <p><b>{% trans "Professor" %}: </b>{% for professor in subject.professors.all %}{% if not forloop.first %},{% endif %} | |
| 210 | - {{professor}}{% if forloop.last %}.{% endif %}{% endfor %}</p> | |
| 211 | - <p> | |
| 212 | - <b>{% trans "Description" %}: </b> | |
| 213 | - <i> | |
| 214 | - {{subject.description}} | |
| 215 | - </i> | |
| 216 | - </p> | |
| 217 | - <div class="row"> | |
| 218 | - <div class="col-xs-6 col-md-6"> | |
| 219 | - <p><b>{% trans "Begining" %}: </b>{{subject.init_date}}</p> | |
| 220 | - </div> | |
| 221 | - <div class="col-xs-6 col-md-6"> | |
| 222 | - <p><b>{% trans "End" %}: </b>{{subject.end_date}}</p> | |
| 237 | + {% endfor %} | |
| 238 | + {% else %} | |
| 239 | + {% for subject in subjects_category %} | |
| 240 | + {% if subject.category.name == request.GET.category %} | |
| 241 | + <div class="panel panel-info"> | |
| 242 | + <div class="panel-heading headingTwo ui-sortable-handle" role="tab"> | |
| 243 | + <div class="row"> | |
| 244 | + <div class="col-xs-9 col-md-10 titleTopic"> | |
| 245 | + <a role="button" data-toggle="collapse" data-parent="#accordion" href=".collapseTwo" aria-expanded="true" aria-controls="collapseTwo"> | |
| 246 | + <h4 style="color:white">{{subject.name}}</h4> | |
| 247 | + </a> | |
| 248 | + </div> | |
| 249 | + <div class="col-xs-3 col-md-2" id="divMoreActions"> | |
| 250 | + <div class="btn-group"> | |
| 251 | + <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | |
| 252 | + <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i> | |
| 253 | + </button> | |
| 254 | + <ul class="dropdown-menu" aria-labelledby="moreActions"> | |
| 255 | + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal3"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i> Replicate</a></li> | |
| 256 | + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#removeSubject2"><i class="fa fa-trash fa-fw" aria-hidden="true"></i> Remove</a></li> | |
| 257 | + </ul> | |
| 258 | + </div> | |
| 259 | + </div> | |
| 260 | + </div> | |
| 223 | 261 | </div> |
| 262 | + <div class="panel-body"> | |
| 263 | + <p><b>{% trans "Professor" %}: </b>{% for professor in subject.professors.all %}{% if not forloop.first %},{% endif %} | |
| 264 | + {{professor}}{% if forloop.last %}.{% endif %}{% endfor %}</p> | |
| 265 | + <p> | |
| 266 | + <b>{% trans "Description" %}: </b> | |
| 267 | + <i> | |
| 268 | + {{subject.description}} | |
| 269 | + </i> | |
| 270 | + </p> | |
| 271 | + <div class="row"> | |
| 272 | + <div class="col-xs-6 col-md-6"> | |
| 273 | + <p><b>{% trans "Begining" %}: </b>{{subject.init_date}}</p> | |
| 274 | + </div> | |
| 275 | + <div class="col-xs-6 col-md-6"> | |
| 276 | + <p><b>{% trans "End" %}: </b>{{subject.end_date}}</p> | |
| 277 | + </div> | |
| 278 | + </div> | |
| 279 | + <a href="{% url 'course:view_subject' subject.slug %}" class="btn btn-raised btn-default center-block">{% trans 'View Subject' %}<div class="ripple-container"></div></a> | |
| 280 | + </div> | |
| 224 | 281 | </div> |
| 225 | - <a href="{% url 'course:view_subject' subject.slug %}" class="btn btn-raised btn-default center-block">{% trans 'View Subject' %}<div class="ripple-container"></div></a> | |
| 226 | - </div> | |
| 227 | -</div> | |
| 282 | + {% endif %} | |
| 283 | + {% endfor %} | |
| 284 | + {% endif %} | |
| 285 | + | |
| 228 | 286 | {% if user|has_role:'professor' or user|has_role:'system_admin' %} |
| 229 | 287 | |
| 230 | 288 | <div class="form-group"> |
| 231 | - <a href="{% url 'course:create_subject' subject.slug %}" data-toggle="modal" data-target="" class="btn btn-primary btn-lg btn-block btn-raised">{% trans 'Create Subject' %}<div class="ripple-container"></div></a> | |
| 289 | + <a href="#" data-toggle="modal" data-target="" class="btn btn-primary btn-lg btn-block btn-raised">{% trans 'Create Subject' %}<div class="ripple-container"></div></a> | |
| 232 | 290 | </div> |
| 233 | 291 | {% endif %} |
| 234 | 292 | |
| 235 | - | |
| 236 | -{% endfor %} | |
| 237 | - | |
| 238 | - | |
| 239 | 293 | <!-- MODAL REMOVE --> |
| 240 | 294 | <div class="modal" id="removeSubject2"> |
| 241 | 295 | <div class="modal-dialog"> | ... | ... |
courses/templates/subject/form_view_teacher.html
| 1 | - {% load static i18n list_topic_foruns permission_tags %} | |
| 1 | + {% load static i18n list_topic_foruns permission_tags widget_tweaks %} | |
| 2 | 2 | |
| 3 | 3 | {% block javascript %} |
| 4 | 4 | <script type="text/javascript" src="{% static 'js/forum.js' %}"></script> |
| 5 | + <script type="text/javascript" src="{% static 'js/material.js' %}"></script> | |
| 5 | 6 | {% endblock %} |
| 6 | 7 | |
| 7 | 8 | <div class="panel-group accordion ui-accordion ui-widget ui-helper-reset ui-sortable" role="tablist" aria-multiselectable="false"> |
| ... | ... | @@ -52,14 +53,17 @@ |
| 52 | 53 | <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> |
| 53 | 54 | <ul class="dropdown-menu" aria-labelledby="dLabel"> |
| 54 | 55 | <li><a href="javascript:void(0)" data-toggle="modal" data-target="#createLinksModal">Create a Link<div class="ripple-container"><div class="ripple ripple-on ripple-out" style="left: 54.5312px; top: 22px; background-color: rgb(0, 150, 136); transform: scale(20);"></div></div></a></li> |
| 55 | - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#createFileModal">Create a file<div class="ripple-container"><div class="ripple ripple-on ripple-out" style="left: 33.5312px; top: 11px; background-color: rgb(0, 150, 136); transform: scale(20);"></div></div></a></li> | |
| 56 | + <li><a href="javascript:createMaterial('{% url 'course:upload_material' %}', '{{ topic.id }}')">{% trans 'Create File' %}<div class="ripple-container"><div class="ripple ripple-on ripple-out" style="left: 33.5312px; top: 11px; background-color: rgb(0, 150, 136); transform: scale(20);"></div></div></a></li> | |
| 56 | 57 | </ul> |
| 57 | 58 | </div> |
| 58 | 59 | </div> |
| 59 | 60 | <ul> |
| 60 | - <li><i class="fa fa-book" aria-hidden="true"></i> <a href="#">Book 1</a></li> | |
| 61 | - <li><i class="fa fa-link" aria-hidden="true"></i> <a href="#" data-toggle="modal" data-target="#linksModal">Link 1</a></li> | |
| 62 | - <li><i class="fa fa-file-code-o" aria-hidden="true"></i> <a href="#" data-toggle="modal" data-target="#embedModal">EMBED Material</a></li> | |
| 61 | + {% for file in files %} | |
| 62 | + <li><i class="fa fa-book" aria-hidden="true"></i> <a href="{{file.file_url}}">{{file}}</a></li> | |
| 63 | + {% endfor %} | |
| 64 | + | |
| 65 | + <!-- <li><i class="fa fa-link" aria-hidden="true"></i> <a href="#" data-toggle="modal" data-target="#linksModal">Link 1</a></li> | |
| 66 | + <li><i class="fa fa-file-code-o" aria-hidden="true"></i> <a href="#" data-toggle="modal" data-target="#embedModal">EMBED Material</a></li>--> | |
| 63 | 67 | </ul> |
| 64 | 68 | </div> |
| 65 | 69 | <div class="col-xs-4 col-md-4"> |
| ... | ... | @@ -70,7 +74,7 @@ |
| 70 | 74 | <div class="dropdown"> |
| 71 | 75 | <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> |
| 72 | 76 | <ul class="dropdown-menu" aria-labelledby="dLabel"> |
| 73 | - <li><a href="javascript:createForum('{% url 'course:forum:create' %}', '{{ topic.id }}')">{% trans 'Create Forum' %}<div class="ripple-container"><div class="ripple ripple-on ripple-out" style="left: 33.5312px; top: 11px; background-color: rgb(0, 150, 136); transform: scale(20);"></div></div></a></li> | |
| 77 | + <li><a href="javascript:createFforum('{% url 'course:forum:create' %}', '{{ topic.id }}')">{% trans 'Create Forum' %}<div class="ripple-container"><div class="ripple ripple-on ripple-out" style="left: 33.5312px; top: 11px; background-color: rgb(0, 150, 136); transform: scale(20);"></div></div></a></li> | |
| 74 | 78 | </ul> |
| 75 | 79 | </div> |
| 76 | 80 | </div> |
| ... | ... | @@ -168,58 +172,23 @@ |
| 168 | 172 | </div> |
| 169 | 173 | <!-- END --> |
| 170 | 174 | |
| 171 | - <!-- MODAL EDIT FILE --> | |
| 172 | 175 | <div class="modal fade" id="editFileModal" tabindex="-1" role="dialog" aria-labelledby="editFileLabel"> |
| 173 | - <div class="modal-dialog" role="document"> | |
| 174 | - <div class="modal-content"> | |
| 175 | - <div class="modal-header"> | |
| 176 | - <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
| 177 | - <h4 class="modal-title" id="editFileLabel">Add File</h4> | |
| 178 | - </div> | |
| 179 | - <div class="modal-body"> | |
| 180 | - <!-- Card --> | |
| 181 | - | |
| 182 | - <form class="form-horizontal"> | |
| 183 | - <fieldset> | |
| 184 | - | |
| 185 | - <div class="form-group"> | |
| 186 | - <label for="inputName" class="col-md-2 control-label">Name</label> | |
| 187 | - | |
| 188 | - <div class="col-md-10"> | |
| 189 | - <input type="text" class="form-control" id="inputText" placeholder="Name" value="Book 1"> | |
| 190 | - </div> | |
| 191 | - </div> | |
| 192 | - | |
| 193 | - <div class="form-group is-empty is-fileinput"> | |
| 194 | - <label for="inputFile" class="col-md-2 control-label">File</label> | |
| 195 | - | |
| 196 | - <div class="col-md-10"> | |
| 197 | - <input type="text" readonly="" class="form-control" placeholder="Browse..."> | |
| 198 | - <input type="file" id="inputFile" multiple=""> | |
| 199 | - </div> | |
| 200 | - </div> | |
| 201 | - | |
| 202 | - | |
| 203 | - <div class="form-group"> | |
| 204 | - <div class="col-md-12 text-center"> | |
| 205 | - <p><b>The file size shouldn't exceed 10MB</b></p> | |
| 206 | - </div> | |
| 207 | - </div> | |
| 208 | - | |
| 209 | - <div class="form-group"> | |
| 210 | - <div class="col-md-12"> | |
| 211 | - <a href="javascript:void(0)" class="btn btn-raised btn-default">Cancel</a> | |
| 212 | - <a href="javascript:void(0)" class="btn btn-raised btn-primary">Submit</a> | |
| 213 | - </div> | |
| 214 | - </div> | |
| 215 | - </fieldset> | |
| 216 | - </form> | |
| 217 | - | |
| 218 | - | |
| 219 | - <!-- .end Card --> | |
| 220 | - </div> | |
| 176 | + <div class="modal-dialog" role="document"> | |
| 177 | + <div class="modal-content"> | |
| 178 | + <div class="modal-header"> | |
| 179 | + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
| 180 | + <h4 class="modal-title" id="editFileLabel">{% trans 'Add File' %}</h4> | |
| 181 | + </div> | |
| 182 | + <div class="modal-body"> | |
| 183 | + <section> | |
| 184 | + <div class="material_form"></div> | |
| 185 | + </section> | |
| 186 | + </div> | |
| 187 | + <div class="modal-footer"> | |
| 188 | + <button type="button" onclick="$('#material_create').submit();" class="btn btn-primary btn-raised">{% trans 'Submit' %}</button> | |
| 189 | + </div> | |
| 190 | + </div> | |
| 221 | 191 | </div> |
| 222 | - </div> | |
| 223 | 192 | </div> |
| 224 | 193 | |
| 225 | 194 | {% if user|has_role:'system_admin' or topic.owner == user%} | ... | ... |
courses/urls.py
| ... | ... | @@ -28,6 +28,7 @@ urlpatterns = [ |
| 28 | 28 | url(r'^forum/', include('forum.urls', namespace = 'forum')), |
| 29 | 29 | url(r'^poll/', include('poll.urls', namespace = 'poll')), |
| 30 | 30 | url(r'^exam/', include('exam.urls', namespace = 'exam')), |
| 31 | + url(r'^upload-material/$', views.UploadMaterialView.as_view(), name='upload_material'), | |
| 31 | 32 | |
| 32 | 33 | |
| 33 | 34 | ... | ... |
courses/views.py
| ... | ... | @@ -13,10 +13,11 @@ from rolepermissions.verifications import has_object_permission |
| 13 | 13 | from django.http import HttpResponseRedirect |
| 14 | 14 | |
| 15 | 15 | from .forms import CourseForm, UpdateCourseForm, CategoryCourseForm, SubjectForm,TopicForm,ActivityForm |
| 16 | -from .models import Course, Subject, CourseCategory,Topic, SubjectCategory,Activity | |
| 16 | +from .models import Course, Subject, CourseCategory,Topic, SubjectCategory,Activity, CategorySubject | |
| 17 | 17 | from core.mixins import NotificationMixin |
| 18 | 18 | from users.models import User |
| 19 | 19 | from files.forms import FileForm |
| 20 | +from files.models import TopicFile | |
| 20 | 21 | |
| 21 | 22 | from datetime import date |
| 22 | 23 | |
| ... | ... | @@ -191,6 +192,23 @@ class CourseView(LoginRequiredMixin, NotificationMixin, generic.DetailView): |
| 191 | 192 | courses = self.request.user.courses.all() |
| 192 | 193 | elif has_role(self.request.user, 'student'): |
| 193 | 194 | courses = self.request.user.courses_student.all() |
| 195 | + | |
| 196 | + categorys_subjects = None | |
| 197 | + if has_role(self.request.user,'professor') or has_role(self.request.user,'system_admin'): | |
| 198 | + categorys_subjects = CategorySubject.objects.filter(subject_category__professors__name = self.request.user.name).distinct() | |
| 199 | + else: | |
| 200 | + categorys_subjects = CategorySubject.objects.filter(subject_category__students__name = self.request.user.name).distinct() | |
| 201 | + | |
| 202 | + subjects_category = Subject.objects.filter(category__name = self.request.GET.get('category')) | |
| 203 | + | |
| 204 | + none = None | |
| 205 | + q = self.request.GET.get('category', None) | |
| 206 | + if q is None: | |
| 207 | + none = True | |
| 208 | + context['none'] = none | |
| 209 | + | |
| 210 | + context['subjects_category'] = subjects_category | |
| 211 | + context['categorys_subjects'] = categorys_subjects | |
| 194 | 212 | context['courses'] = courses |
| 195 | 213 | context['title'] = course.name |
| 196 | 214 | |
| ... | ... | @@ -300,14 +318,36 @@ class SubjectsView(LoginRequiredMixin, generic.ListView): |
| 300 | 318 | return context |
| 301 | 319 | |
| 302 | 320 | def get_context_data(self, **kwargs): |
| 303 | - subject = get_object_or_404(Subject, slug = self.kwargs.get('slug')) | |
| 321 | + | |
| 304 | 322 | context = super(SubjectsView, self).get_context_data(**kwargs) |
| 323 | + subject = get_object_or_404(Subject, slug = self.kwargs.get('slug')) | |
| 305 | 324 | context['course'] = subject.course |
| 306 | 325 | context['subject'] = subject |
| 307 | - context['form_file'] = FileForm | |
| 308 | 326 | context['topics'] = Topic.objects.filter(subject = subject) |
| 327 | + if has_role(self.request.user,'professor') or has_role(self.request.user,'system_admin'): | |
| 328 | + context['files'] = TopicFile.objects.filter(professor__name = self.request.user.name) | |
| 329 | + else: | |
| 330 | + context['files'] = TopicFile.objects.filter(students__name = self.request.user.name) | |
| 331 | + return context | |
| 332 | + | |
| 333 | +class UploadMaterialView(LoginRequiredMixin, generic.edit.CreateView): | |
| 334 | + login_url = reverse_lazy("core:home") | |
| 335 | + redirect_field_name = 'next' | |
| 336 | + | |
| 337 | + template_name = 'files/create_file.html' | |
| 338 | + form_class = FileForm | |
| 339 | + | |
| 340 | + def form_invalid(self, form): | |
| 341 | + context = super(UploadMaterialView, self).form_invalid(form) | |
| 342 | + context.status_code = 400 | |
| 343 | + | |
| 309 | 344 | return context |
| 310 | 345 | |
| 346 | + def get_success_url(self): | |
| 347 | + self.success_url = reverse('course:view_subject', args = (self.object.slug, )) | |
| 348 | + | |
| 349 | + return self.success_url | |
| 350 | + | |
| 311 | 351 | class TopicsView(LoginRequiredMixin, generic.ListView): |
| 312 | 352 | |
| 313 | 353 | login_url = reverse_lazy("core:home") | ... | ... |
exam/migrations/0001_initial.py
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | -# Generated by Django 1.10 on 2016-10-06 19:57 | |
| 2 | +# Generated by Django 1.10 on 2016-10-17 15:49 | |
| 3 | 3 | from __future__ import unicode_literals |
| 4 | 4 | |
| 5 | 5 | from django.db import migrations, models |
| ... | ... | @@ -11,6 +11,7 @@ class Migration(migrations.Migration): |
| 11 | 11 | initial = True |
| 12 | 12 | |
| 13 | 13 | dependencies = [ |
| 14 | + ('courses', '0001_initial'), | |
| 14 | 15 | ] |
| 15 | 16 | |
| 16 | 17 | operations = [ |
| ... | ... | @@ -18,27 +19,26 @@ class Migration(migrations.Migration): |
| 18 | 19 | name='Answer', |
| 19 | 20 | fields=[ |
| 20 | 21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
| 21 | - ('answer', models.CharField(max_length=200, verbose_name='Answer')), | |
| 22 | + ('answer', models.CharField(max_length=300, verbose_name='Answer')), | |
| 22 | 23 | ('order', models.PositiveSmallIntegerField(verbose_name='Order')), |
| 23 | 24 | ], |
| 24 | 25 | options={ |
| 25 | - 'verbose_name_plural': 'Answers', | |
| 26 | 26 | 'ordering': ('order',), |
| 27 | + 'verbose_name_plural': 'Answers', | |
| 27 | 28 | 'verbose_name': 'Answer', |
| 28 | 29 | }, |
| 29 | 30 | ), |
| 30 | 31 | migrations.CreateModel( |
| 31 | 32 | name='Exam', |
| 32 | 33 | fields=[ |
| 33 | - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
| 34 | - ('name', models.CharField(max_length=100, verbose_name='Name')), | |
| 35 | - ('beginDate', models.DateTimeField(auto_now_add=True, verbose_name='Start Date')), | |
| 36 | - ('endDate', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), | |
| 34 | + ('activity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Activity')), | |
| 35 | + ('begin_date', models.DateField(verbose_name='Begin of Course Date')), | |
| 37 | 36 | ], |
| 38 | 37 | options={ |
| 39 | 38 | 'verbose_name_plural': 'Exams', |
| 40 | 39 | 'verbose_name': 'Exam', |
| 41 | 40 | }, |
| 41 | + bases=('courses.activity',), | |
| 42 | 42 | ), |
| 43 | 43 | migrations.AddField( |
| 44 | 44 | model_name='answer', | ... | ... |
exam/migrations/0002_auto_20161013_2047.py
| ... | ... | @@ -1,50 +0,0 @@ |
| 1 | -# -*- coding: utf-8 -*- | |
| 2 | -# Generated by Django 1.10 on 2016-10-13 23:47 | |
| 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', '0005_file'), | |
| 13 | - ('exam', '0001_initial'), | |
| 14 | - ] | |
| 15 | - | |
| 16 | - operations = [ | |
| 17 | - migrations.RemoveField( | |
| 18 | - model_name='exam', | |
| 19 | - name='beginDate', | |
| 20 | - ), | |
| 21 | - migrations.RemoveField( | |
| 22 | - model_name='exam', | |
| 23 | - name='endDate', | |
| 24 | - ), | |
| 25 | - migrations.RemoveField( | |
| 26 | - model_name='exam', | |
| 27 | - name='id', | |
| 28 | - ), | |
| 29 | - migrations.RemoveField( | |
| 30 | - model_name='exam', | |
| 31 | - name='name', | |
| 32 | - ), | |
| 33 | - migrations.AddField( | |
| 34 | - model_name='exam', | |
| 35 | - name='activity_ptr', | |
| 36 | - field=models.OneToOneField(auto_created=True, default=None, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Activity'), | |
| 37 | - preserve_default=False, | |
| 38 | - ), | |
| 39 | - migrations.AddField( | |
| 40 | - model_name='exam', | |
| 41 | - name='begin_date', | |
| 42 | - field=models.DateField(default=None, verbose_name='Begin of Course Date'), | |
| 43 | - preserve_default=False, | |
| 44 | - ), | |
| 45 | - migrations.AlterField( | |
| 46 | - model_name='answer', | |
| 47 | - name='answer', | |
| 48 | - field=models.CharField(max_length=300, verbose_name='Answer'), | |
| 49 | - ), | |
| 50 | - ] |
files/admin.py
files/migrations/0001_initial.py
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | -# Generated by Django 1.10 on 2016-10-13 16:12 | |
| 2 | +# Generated by Django 1.10 on 2016-10-17 15:49 | |
| 3 | 3 | from __future__ import unicode_literals |
| 4 | 4 | |
| 5 | 5 | from django.db import migrations, models |
| ... | ... | @@ -12,8 +12,8 @@ class Migration(migrations.Migration): |
| 12 | 12 | initial = True |
| 13 | 13 | |
| 14 | 14 | dependencies = [ |
| 15 | - ('core', '0002_mymetype'), | |
| 16 | - ('courses', '0004_auto_20161011_1951'), | |
| 15 | + ('courses', '0001_initial'), | |
| 16 | + ('core', '0001_initial'), | |
| 17 | 17 | ] |
| 18 | 18 | |
| 19 | 19 | operations = [ |
| ... | ... | @@ -26,8 +26,8 @@ class Migration(migrations.Migration): |
| 26 | 26 | ('file_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='topic_files', to='core.MymeType', verbose_name='Type file')), |
| 27 | 27 | ], |
| 28 | 28 | options={ |
| 29 | - 'verbose_name': 'File', | |
| 30 | 29 | 'verbose_name_plural': 'Files', |
| 30 | + 'verbose_name': 'File', | |
| 31 | 31 | }, |
| 32 | 32 | bases=('courses.material',), |
| 33 | 33 | ), | ... | ... |
| ... | ... | @@ -0,0 +1,24 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2016-10-17 15:49 | |
| 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 | + ] | ... | ... |
files/models.py
| ... | ... | @@ -2,6 +2,7 @@ from django.db import models |
| 2 | 2 | from django.utils.translation import ugettext_lazy as _ |
| 3 | 3 | from core.models import MymeType |
| 4 | 4 | from courses.models import Material |
| 5 | +from users.models import User | |
| 5 | 6 | |
| 6 | 7 | """ |
| 7 | 8 | Function to return the path where the file should be saved |
| ... | ... | @@ -15,6 +16,8 @@ def file_path(instance, filename): |
| 15 | 16 | It's like a support material for the students. |
| 16 | 17 | """ |
| 17 | 18 | class TopicFile(Material): |
| 19 | + | |
| 20 | + professor = models.ManyToManyField(User,verbose_name=_('Professors'), related_name='file_professors') | |
| 18 | 21 | description = models.TextField(_('Description'), blank=True) |
| 19 | 22 | file_url = models.FileField(verbose_name = _("File"), upload_to = file_path) |
| 20 | 23 | file_type = models.ForeignKey(MymeType, verbose_name=_('Type file'), related_name='topic_files') | ... | ... |
files/templates/files/create_file.html
| 1 | -{% load widget_tweaks i18n %} | |
| 2 | -<!-- MODAL CREATE FILE --> | |
| 3 | -<div class="modal fade" id="createFileModal" tabindex="-1" role="dialog" aria-labelledby="createFileLabel" style="display: none;"> | |
| 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="createFileLabel">{% trans 'Add File' %}</h4> | |
| 9 | - </div> | |
| 10 | - <div class="modal-body"> | |
| 11 | - <!-- Card --> | |
| 12 | - <form class="form-horizontal"> | |
| 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 | - <fieldset> | |
| 25 | - {% for field in form_file %} | |
| 26 | - <div class="form-group is-empy{% if form.has_error %} has-error {% endif %} is-fileinput"> | |
| 27 | - <div class="col-md-12"> | |
| 28 | - {% if field.field.required %} | |
| 29 | - <label for="{{ field.auto_id }}" class="control-label">{{ field.label }}<span>*</span></label> | |
| 30 | - {% else %} | |
| 31 | - <label for="{{ field.auto_id }}" class=" control-label">{{ field.label }}</label> | |
| 32 | - {% endif %} | |
| 33 | - {% if field.auto_id == 'id_file_url' %} | |
| 34 | - {% render_field field class='form-control input-sm' %} | |
| 35 | - <div class="input-group"> | |
| 36 | - <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your file...' %}"> | |
| 37 | - <span class="input-group-btn input-group-sm"> | |
| 38 | - <button type="button" class="btn btn-fab btn-fab-mini"> | |
| 39 | - <i class="material-icons">attach_file</i> | |
| 40 | - </button> | |
| 41 | - </span> | |
| 42 | - </div> | |
| 43 | - {% else %} | |
| 44 | - {% render_field field class='form-control input-sm' %} | |
| 45 | - <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
| 46 | - {% endif %} | |
| 47 | - </div> | |
| 48 | - | |
| 49 | - {% if field.errors %} | |
| 50 | - <div class="alert alert-danger alert-dismissible" role="alert"> | |
| 51 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
| 52 | - <span aria-hidden="true">×</span> | |
| 53 | - </button> | |
| 54 | - <ul> | |
| 55 | - {% for error in field.errors %} | |
| 56 | - <li>{{ error }}</li> | |
| 57 | - {% endfor %} | |
| 58 | - </ul> | |
| 59 | - </div> | |
| 60 | - {% endif %} | |
| 61 | - </div> | |
| 62 | - {% endfor %} | |
| 1 | +{% load widget_tweaks i18n %} | |
| 63 | 2 | |
| 64 | - <div class="form-group"> | |
| 65 | - <div class="col-md-12 text-center"> | |
| 66 | - <p><b>The file size shouldn't exceed 10MB</b></p> | |
| 67 | - </div> | |
| 3 | +<form method="post" id="material_create" enctype="multipart/form-data" action="{% if material %}{% else %}{% url 'course:upload_material' %}{% endif %}"> | |
| 4 | + {% csrf_token %} | |
| 5 | + {% for field in form %} | |
| 6 | + <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput"> | |
| 7 | + {% if field.field.widget.input_type == 'hidden' %} | |
| 8 | + {% render_field field class='form-control' %} | |
| 9 | + {% else %} | |
| 10 | + {% if field.field.required %} | |
| 11 | + <label for="{{ field.auto_id }}" class="control-label">{{ field.label }}<span>*</span></label> | |
| 12 | + {% else %} | |
| 13 | + <label for="{{ field.auto_id }}" class=" control-label">{{ field.label }}</label> | |
| 14 | + {% endif %} | |
| 15 | + <label for="{{ field.auto_id }}">{{ field.label }}</label> | |
| 16 | + {% render_field field %} | |
| 17 | + <span class="help-block">{{ field.help_text }}</span> | |
| 18 | + {% if field.auto_id == 'id_file_url' %} | |
| 19 | + {% render_field field class='form-control input-sm' %} | |
| 20 | + <div class="input-group"> | |
| 21 | + <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your file...' %}"> | |
| 22 | + <span class="input-group-btn input-group-sm"> | |
| 23 | + <button type="button" class="btn btn-fab btn-fab-mini"> | |
| 24 | + <i class="material-icons">attach_file</i> | |
| 25 | + </button> | |
| 26 | + </span> | |
| 68 | 27 | </div> |
| 69 | - | |
| 70 | - <div class="form-group"> | |
| 71 | - <div class="col-md-12"> | |
| 72 | - <a href="javascript:void(0)" class="btn btn-raised btn-default">Cancel<div class="ripple-container"></div></a> | |
| 73 | - <a href="javascript:void(0)" class="btn btn-raised btn-primary">Submit</a> | |
| 74 | - </div> | |
| 28 | + {% else %} | |
| 29 | + {% render_field field class='form-control input-sm' %} | |
| 30 | + <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
| 31 | + {% endif %} | |
| 32 | + {% if field.errors %} | |
| 33 | + <div class="row"> | |
| 34 | + <br /> | |
| 35 | + <div class="alert alert-danger alert-dismissible" role="alert"> | |
| 36 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
| 37 | + <span aria-hidden="true">×</span> | |
| 38 | + </button> | |
| 39 | + <ul> | |
| 40 | + {% for error in field.errors %} | |
| 41 | + <li>{{ error }}</li> | |
| 42 | + {% endfor %} | |
| 43 | + </ul> | |
| 75 | 44 | </div> |
| 76 | - </fieldset> | |
| 77 | - </form> | |
| 78 | - <!-- .end Card --> | |
| 79 | - </div> | |
| 45 | + </div> | |
| 46 | + {% endif %} | |
| 47 | + {% endif %} | |
| 80 | 48 | </div> |
| 81 | - </div> | |
| 82 | -</div> | |
| 49 | + {% endfor %} | |
| 50 | +</form> | |
| 83 | 51 | <!-- EndModal --> |
| 84 | 52 | \ No newline at end of file | ... | ... |
forum/migrations/0001_initial.py
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | -# Generated by Django 1.10 on 2016-10-05 13:38 | |
| 2 | +# Generated by Django 1.10 on 2016-10-17 15:49 | |
| 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 = [ |
| ... | ... | @@ -26,8 +24,8 @@ class Migration(migrations.Migration): |
| 26 | 24 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Create Date')), |
| 27 | 25 | ], |
| 28 | 26 | options={ |
| 29 | - 'verbose_name': 'Forum', | |
| 30 | 27 | 'verbose_name_plural': 'Foruns', |
| 28 | + 'verbose_name': 'Forum', | |
| 31 | 29 | }, |
| 32 | 30 | bases=('courses.activity',), |
| 33 | 31 | ), |
| ... | ... | @@ -38,12 +36,10 @@ 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 | - 'verbose_name': 'Post', | |
| 46 | 41 | 'verbose_name_plural': 'Posts', |
| 42 | + 'verbose_name': 'Post', | |
| 47 | 43 | }, |
| 48 | 44 | ), |
| 49 | 45 | migrations.CreateModel( |
| ... | ... | @@ -54,11 +50,10 @@ 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 | - 'verbose_name': 'Post Answer', | |
| 61 | 55 | 'verbose_name_plural': 'Post Answers', |
| 56 | + 'verbose_name': 'Post Answer', | |
| 62 | 57 | }, |
| 63 | 58 | ), |
| 64 | 59 | ] | ... | ... |
| ... | ... | @@ -0,0 +1,35 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2016-10-17 15:49 | |
| 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 | + ('forum', '0001_initial'), | |
| 16 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 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-10-05 13:38 | |
| 2 | +# Generated by Django 1.10 on 2016-10-17 15:49 | |
| 3 | 3 | from __future__ import unicode_literals |
| 4 | 4 | |
| 5 | 5 | from django.db import migrations, models |
| ... | ... | @@ -23,9 +23,22 @@ class Migration(migrations.Migration): |
| 23 | 23 | ('order', models.PositiveSmallIntegerField(verbose_name='Order')), |
| 24 | 24 | ], |
| 25 | 25 | options={ |
| 26 | - 'verbose_name': 'Answer', | |
| 27 | - 'verbose_name_plural': 'Answers', | |
| 28 | 26 | 'ordering': ('order',), |
| 27 | + 'verbose_name_plural': 'Answers', | |
| 28 | + 'verbose_name': 'Answer', | |
| 29 | + }, | |
| 30 | + ), | |
| 31 | + migrations.CreateModel( | |
| 32 | + name='AnswersStudent', | |
| 33 | + fields=[ | |
| 34 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
| 35 | + ('status', models.BooleanField(default=False, verbose_name='Answered')), | |
| 36 | + ('answered_in', models.DateTimeField(auto_now=True, verbose_name='Answered Date')), | |
| 37 | + ('answer', models.ManyToManyField(related_name='answers_stundet', to='poll.Answer', verbose_name='Answers Students')), | |
| 38 | + ], | |
| 39 | + options={ | |
| 40 | + 'verbose_name_plural': 'Answers Student', | |
| 41 | + 'verbose_name': 'Answer Stundent', | |
| 29 | 42 | }, |
| 30 | 43 | ), |
| 31 | 44 | migrations.CreateModel( |
| ... | ... | @@ -40,8 +53,8 @@ class Migration(migrations.Migration): |
| 40 | 53 | bases=('courses.activity',), |
| 41 | 54 | ), |
| 42 | 55 | migrations.AddField( |
| 43 | - model_name='answer', | |
| 56 | + model_name='answersstudent', | |
| 44 | 57 | name='poll', |
| 45 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='poll.Poll', verbose_name='Answers'), | |
| 58 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundet', to='poll.Poll', verbose_name='Poll'), | |
| 46 | 59 | ), |
| 47 | 60 | ] | ... | ... |
poll/migrations/0002_answersstudent.py
| ... | ... | @@ -1,33 +0,0 @@ |
| 1 | -# -*- coding: utf-8 -*- | |
| 2 | -# Generated by Django 1.10 on 2016-10-12 18:26 | |
| 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 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
| 14 | - ('poll', '0001_initial'), | |
| 15 | - ] | |
| 16 | - | |
| 17 | - operations = [ | |
| 18 | - migrations.CreateModel( | |
| 19 | - name='AnswersStudent', | |
| 20 | - fields=[ | |
| 21 | - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
| 22 | - ('status', models.BooleanField(default=False, verbose_name='Answered')), | |
| 23 | - ('answered_in', models.DateTimeField(auto_now=True, verbose_name='Answered Date')), | |
| 24 | - ('answer', models.ManyToManyField(related_name='answers_stundet', to='poll.Answer', verbose_name='Answers Students')), | |
| 25 | - ('poll', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundet', to='poll.Poll', verbose_name='Answers')), | |
| 26 | - ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundent', to=settings.AUTH_USER_MODEL, verbose_name='Student')), | |
| 27 | - ], | |
| 28 | - options={ | |
| 29 | - 'verbose_name': 'Answer Stundent', | |
| 30 | - 'verbose_name_plural': 'Answers Student', | |
| 31 | - }, | |
| 32 | - ), | |
| 33 | - ] |
| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.10 on 2016-10-17 15:49 | |
| 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 | + ('poll', '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='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 | + ] | ... | ... |
poll/migrations/0003_auto_20161012_1638.py
| ... | ... | @@ -1,21 +0,0 @@ |
| 1 | -# -*- coding: utf-8 -*- | |
| 2 | -# Generated by Django 1.10 on 2016-10-12 19:38 | |
| 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 | - ('poll', '0002_answersstudent'), | |
| 13 | - ] | |
| 14 | - | |
| 15 | - operations = [ | |
| 16 | - migrations.AlterField( | |
| 17 | - model_name='answersstudent', | |
| 18 | - name='poll', | |
| 19 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundet', to='poll.Poll', verbose_name='Poll'), | |
| 20 | - ), | |
| 21 | - ] |
users/migrations/0001_initial.py
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | -# Generated by Django 1.10 on 2016-10-05 13:37 | |
| 2 | +# Generated by Django 1.10 on 2016-10-17 15:49 | |
| 3 | 3 | from __future__ import unicode_literals |
| 4 | 4 | |
| 5 | 5 | import django.contrib.auth.models |
| ... | ... | @@ -42,8 +42,8 @@ class Migration(migrations.Migration): |
| 42 | 42 | ('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')), |
| 43 | 43 | ], |
| 44 | 44 | options={ |
| 45 | - 'verbose_name': 'User', | |
| 46 | 45 | 'verbose_name_plural': 'Users', |
| 46 | + 'verbose_name': 'User', | |
| 47 | 47 | }, |
| 48 | 48 | managers=[ |
| 49 | 49 | ('objects', django.contrib.auth.models.UserManager()), | ... | ... |