diff --git a/core/custom_annotations.py b/core/custom_annotations.py new file mode 100644 index 0000000000000000000000000000000000000000..857df0b603c923e084f42a8992ebb9981939c47e --- /dev/null +++ b/core/custom_annotations.py @@ -0,0 +1,21 @@ +from django.contrib.auth.decorators import user_passes_test + + +"""I collect custom decorators here that I use for the simple premission system + +Currently the following options are available + - group_required + - in_groups +""" + + +def in_groups(user, group_list): + return bool(user.groups.filter(name__in=group_list)) or user.is_superuser + + +def group_required(*group_names): + """Requires user membership in at least one of the groups passed in.""" + def _in_groups(u): + if u.is_authenticated(): + return in_groups(u, group_names) + return user_passes_test(_in_groups) diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py deleted file mode 100644 index 84f7cc74134a44de55ab286e84c31bd4f06b1d09..0000000000000000000000000000000000000000 --- a/core/migrations/0001_initial.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-03 15:39 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='SubmissionType', - fields=[ - ('type_id', models.CharField(max_length=20, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=50)), - ('correct_solution', models.TextField()), - ('correction_guideline', models.TextField()), - ], - ), - ] diff --git a/core/migrations/0001_squashed_0034_auto_20170322_1304.py b/core/migrations/0001_squashed_0034_auto_20170322_1304.py new file mode 100644 index 0000000000000000000000000000000000000000..791b608cccfac35725a7c59936ace173284a6940 --- /dev/null +++ b/core/migrations/0001_squashed_0034_auto_20170322_1304.py @@ -0,0 +1,292 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-03-23 00:24 +from __future__ import unicode_literals + +import core.models +from django.conf import settings +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + replaces = [('core', '0001_initial'), ('core', '0002_auto_20170303_1837'), ('core', '0003_auto_20170303_2053'), ('core', '0004_submission_final_feedback'), ('core', '0005_auto_20170304_1200'), ('core', '0006_auto_20170304_1523'), ('core', '0007_feedback_slug'), ('core', '0008_auto_20170304_1612'), ('core', '0009_auto_20170304_1614'), ('core', '0010_auto_20170304_1741'), ('core', '0011_auto_20170306_1327'), ('core', '0012_auto_20170306_1450'), ('core', '0013_auto_20170306_1452'), ('core', '0014_auto_20170306_1504'), ('core', '0015_auto_20170306_1525'), ('core', '0016_auto_20170306_1535'), ('core', '0017_auto_20170306_1550'), ('core', '0018_auto_20170306_1605'), ('core', '0019_auto_20170307_1735'), ('core', '0020_auto_20170307_2031'), ('core', '0021_auto_20170307_2122'), ('core', '0022_auto_20170308_1439'), ('core', '0023_auto_20170310_1422'), ('core', '0024_auto_20170310_1502'), ('core', '0025_auto_20170311_1637'), ('core', '0026_submission_seen'), ('core', '0027_submissiontype_description'), ('core', '0028_auto_20170314_1726'), ('core', '0029_feedback_empty'), ('core', '0030_auto_20170315_1444'), ('core', '0031_auto_20170315_1603'), ('core', '0032_auto_20170315_1609'), ('core', '0033_auto_20170321_2128'), ('core', '0034_auto_20170322_1304')] + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='SubmissionType', + fields=[ + ('type_id', models.CharField(max_length=20, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=50)), + ('correct_solution', models.TextField()), + ('correction_guideline', models.TextField()), + ], + ), + migrations.CreateModel( + name='Feedback', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('score', models.PositiveIntegerField(default=0)), + ('text', models.TextField()), + ('of_reviewer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reviewd_submissions', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Feedback', + 'verbose_name_plural': 'Feedbacks', + }, + ), + migrations.CreateModel( + name='Student', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('matrikel_no', models.PositiveIntegerField(default=0, unique=True)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='Submission', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('pre_corrections', models.TextField()), + ('student', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='core.Student')), + ], + options={ + 'verbose_name': 'Submission', + 'verbose_name_plural': 'Submissions', + }, + ), + migrations.AlterModelOptions( + name='submissiontype', + options={'verbose_name': 'SubmissionType', 'verbose_name_plural': 'SubmissionTypes'}, + ), + migrations.AddField( + model_name='submissiontype', + name='full_score', + field=models.PositiveIntegerField(default=0), + ), + migrations.AddField( + model_name='submission', + name='submission_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='submissions', to='core.SubmissionType'), + ), + migrations.AddField( + model_name='feedback', + name='of_submission', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Submission'), + ), + migrations.AddField( + model_name='feedback', + name='of_tutor', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='corrected_submissions', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterModelOptions( + name='feedback', + options={'verbose_name': 'Feedback', 'verbose_name_plural': 'Feedback Set'}, + ), + migrations.AlterModelOptions( + name='student', + options={'verbose_name': 'Student', 'verbose_name_plural': 'Student Set'}, + ), + migrations.AddField( + model_name='submission', + name='submission_text', + field=models.TextField(), + ), + migrations.RemoveField( + model_name='feedback', + name='of_reviewer', + ), + migrations.AddField( + model_name='feedback', + name='of_reviewer', + field=models.ManyToManyField(blank=True, related_name='reviewd_submissions', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='submission', + name='pre_corrections', + field=models.TextField(blank=True), + ), + migrations.AddField( + model_name='feedback', + name='slug', + field=models.SlugField(editable=False), + ), + migrations.AlterField( + model_name='submission', + name='student', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Student'), + ), + migrations.CreateModel( + name='SubmissionStatus', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('status', models.CharField(choices=[('R', 'READY'), ('CP', 'CORRECTION_IN_PROGRESS'), ('FL', 'FEEDBACK_LIMIT_REACHED'), ('RE', 'REVIEWED')], default=('R', 'READY'), max_length=2)), + ('feedback_counter', models.PositiveIntegerField(default=0, editable=False)), + ('final_feedback', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.Feedback')), + ('submission', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='core.Submission')), + ], + ), + migrations.AlterModelOptions( + name='submissionstatus', + options={'verbose_name': 'Submission Status', 'verbose_name_plural': 'SubmissionStatus Set'}, + ), + migrations.RemoveField( + model_name='submissiontype', + name='type_id', + ), + migrations.AddField( + model_name='submissiontype', + name='id', + field=models.AutoField(auto_created=True, default=123, primary_key=True, serialize=False, verbose_name='ID'), + preserve_default=False, + ), + migrations.AlterModelOptions( + name='submission', + options={'verbose_name': 'Submission', 'verbose_name_plural': 'Submission Set'}, + ), + migrations.AlterModelOptions( + name='submissiontype', + options={'verbose_name': 'SubmissionType', 'verbose_name_plural': 'SubmissionType Set'}, + ), + migrations.RemoveField( + model_name='submissionstatus', + name='submission', + ), + migrations.RemoveField( + model_name='submissionstatus', + name='feedback_counter', + ), + migrations.AlterField( + model_name='submissionstatus', + name='status', + field=models.CharField(choices=[('R', 'READY'), ('CP', 'CORRECTION_IN_PROGRESS'), ('FL', 'FEEDBACK_LIMIT_REACHED'), ('RE', 'REVIEWED')], default='R', max_length=2), + ), + migrations.RenameField( + model_name='submissiontype', + old_name='correction_guideline', + new_name='possible_solution', + ), + migrations.AlterField( + model_name='submissionstatus', + name='status', + field=models.PositiveIntegerField(choices=[(0, 'READY'), (1, 'IN_PROGRESS'), (2, 'LIMIT_REACHED'), (3, 'REVIEWED')], default=0), + ), + migrations.RenameField( + model_name='submission', + old_name='submission_text', + new_name='text', + ), + migrations.RenameField( + model_name='submission', + old_name='submission_type', + new_name='type', + ), + migrations.RenameField( + model_name='submissiontype', + old_name='correct_solution', + new_name='task_description', + ), + migrations.AlterField( + model_name='submissionstatus', + name='status', + field=models.PositiveIntegerField(choices=[(0, 'READY'), (1, 'IN_PROGRESS'), (2, 'LIMIT_REACHED')], default=0), + ), + migrations.AlterField( + model_name='feedback', + name='slug', + field=models.SlugField(editable=False, unique=True), + ), + migrations.AlterField( + model_name='feedback', + name='of_submission', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feedback_list', to='core.Submission'), + ), + migrations.AddField( + model_name='feedback', + name='final', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='submissionstatus', + name='status', + field=models.PositiveIntegerField(choices=[(0, 'READY'), (1, 'LIMIT_REACHED')], default=0), + ), + migrations.AlterField( + model_name='feedback', + name='score', + field=models.PositiveIntegerField(default=0, validators=[django.core.validators.MaxValueValidator(models.PositiveIntegerField(default=1000, editable=False)), django.core.validators.MinValueValidator(0)]), + ), + migrations.AlterField( + model_name='feedback', + name='score', + field=models.PositiveIntegerField(default=0), + ), + migrations.RemoveField( + model_name='submissionstatus', + name='final_feedback', + ), + migrations.AddField( + model_name='submission', + name='slug', + field=models.SlugField(default=core.models.random_slug, editable=False, unique=True), + ), + migrations.AddField( + model_name='submission', + name='seen', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='submissiontype', + name='correction_guideline', + field=models.TextField(default=2), + ), + migrations.AddField( + model_name='feedback', + name='empty', + field=models.BooleanField(default=True), + ), + migrations.RemoveField( + model_name='feedback', + name='of_reviewer', + ), + migrations.AddField( + model_name='feedback', + name='of_reviewer', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reviewed_submissions', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='feedback', + name='of_submission', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feedback', to='core.Submission'), + ), + migrations.AddField( + model_name='submission', + name='final_feedback', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.Feedback'), + ), + migrations.AlterField( + model_name='feedback', + name='of_submission', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feedback_list', to='core.Submission'), + ), + migrations.AddField( + model_name='submissiontype', + name='slug', + field=models.SlugField(default=core.models.random_slug, editable=False, unique=True), + ), + migrations.AlterField( + model_name='feedback', + name='slug', + field=models.SlugField(default=core.models.random_slug, editable=False, unique=True), + ), + migrations.DeleteModel( + name='SubmissionStatus', + ), + ] diff --git a/core/migrations/0002_auto_20170303_1837.py b/core/migrations/0002_auto_20170303_1837.py deleted file mode 100644 index 3c809d2658ccb6d5dd23843b48c5ff104b706c2a..0000000000000000000000000000000000000000 --- a/core/migrations/0002_auto_20170303_1837.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-03 18:37 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('core', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='Feedback', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('score', models.PositiveIntegerField(default=0)), - ('text', models.TextField()), - ('of_reviewer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reviewd_submissions', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'verbose_name': 'Feedback', - 'verbose_name_plural': 'Feedbacks', - }, - ), - migrations.CreateModel( - name='Student', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('matrikel_no', models.PositiveIntegerField(default=0, unique=True)), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - ), - migrations.CreateModel( - name='Submission', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('pre_corrections', models.TextField()), - ('student', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='core.Student')), - ], - options={ - 'verbose_name': 'Submission', - 'verbose_name_plural': 'Submissions', - }, - ), - migrations.AlterModelOptions( - name='submissiontype', - options={'verbose_name': 'SubmissionType', 'verbose_name_plural': 'SubmissionTypes'}, - ), - migrations.AddField( - model_name='submissiontype', - name='full_score', - field=models.PositiveIntegerField(default=0), - ), - migrations.AddField( - model_name='submission', - name='submission_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='submissions', to='core.SubmissionType'), - ), - migrations.AddField( - model_name='feedback', - name='of_submission', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Submission'), - ), - migrations.AddField( - model_name='feedback', - name='of_tutor', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='corrected_submissions', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/core/migrations/0027_submissiontype_description.py b/core/migrations/0002_auto_20170323_0026.py similarity index 51% rename from core/migrations/0027_submissiontype_description.py rename to core/migrations/0002_auto_20170323_0026.py index 3e2c9f1c9b47da146c5067e5c1f00ebea464027b..d8cd5fd0098cb322ac243e6c1084378ac34358b5 100644 --- a/core/migrations/0027_submissiontype_description.py +++ b/core/migrations/0002_auto_20170323_0026.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-14 17:23 +# Generated by Django 1.10.6 on 2017-03-23 00:26 from __future__ import unicode_literals from django.db import migrations, models @@ -8,14 +8,13 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('core', '0026_submission_seen'), + ('core', '0001_squashed_0034_auto_20170322_1304'), ] operations = [ - migrations.AddField( + migrations.AlterField( model_name='submissiontype', - name='description', - field=models.TextField(default=2), - preserve_default=False, + name='correction_guideline', + field=models.TextField(), ), ] diff --git a/core/migrations/0003_auto_20170303_2053.py b/core/migrations/0003_auto_20170303_2053.py deleted file mode 100644 index 1419821275dd0c81f1c859a98d4f5323874389dd..0000000000000000000000000000000000000000 --- a/core/migrations/0003_auto_20170303_2053.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-03 20:53 -from __future__ import unicode_literals - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('core', '0002_auto_20170303_1837'), - ] - - operations = [ - migrations.AlterModelOptions( - name='feedback', - options={'verbose_name': 'Feedback', 'verbose_name_plural': 'Feedback Set'}, - ), - migrations.AlterModelOptions( - name='student', - options={'verbose_name': 'Student', 'verbose_name_plural': 'Students'}, - ), - migrations.AddField( - model_name='submission', - name='submission_text', - field=models.TextField(blank=True), - ), - migrations.RemoveField( - model_name='feedback', - name='of_reviewer', - ), - migrations.AddField( - model_name='feedback', - name='of_reviewer', - field=models.ManyToManyField(related_name='reviewd_submissions', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/core/migrations/0004_submission_final_feedback.py b/core/migrations/0004_submission_final_feedback.py deleted file mode 100644 index d6cacba863fd38ace514c6cbc4f488768eec9287..0000000000000000000000000000000000000000 --- a/core/migrations/0004_submission_final_feedback.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-04 09:29 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0003_auto_20170303_2053'), - ] - - operations = [ - migrations.AddField( - model_name='submission', - name='final_feedback', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.Feedback'), - ), - ] diff --git a/core/migrations/0005_auto_20170304_1200.py b/core/migrations/0005_auto_20170304_1200.py deleted file mode 100644 index 513af0ba0557afb16a68436f54cc356a6a7c2f37..0000000000000000000000000000000000000000 --- a/core/migrations/0005_auto_20170304_1200.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-04 12:00 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0004_submission_final_feedback'), - ] - - operations = [ - migrations.AlterField( - model_name='submission', - name='pre_corrections', - field=models.TextField(blank=True), - ), - migrations.AlterField( - model_name='submission', - name='submission_text', - field=models.TextField(), - ), - ] diff --git a/core/migrations/0006_auto_20170304_1523.py b/core/migrations/0006_auto_20170304_1523.py deleted file mode 100644 index ff15887e88d2892764291d2d12b70ebd925a3f3c..0000000000000000000000000000000000000000 --- a/core/migrations/0006_auto_20170304_1523.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-04 15:23 -from __future__ import unicode_literals - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0005_auto_20170304_1200'), - ] - - operations = [ - migrations.AlterField( - model_name='feedback', - name='of_reviewer', - field=models.ManyToManyField(blank=True, related_name='reviewd_submissions', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/core/migrations/0007_feedback_slug.py b/core/migrations/0007_feedback_slug.py deleted file mode 100644 index f0c12cb17e360b6ee18cc69d8b3e5630873ea4dd..0000000000000000000000000000000000000000 --- a/core/migrations/0007_feedback_slug.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-04 16:05 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0006_auto_20170304_1523'), - ] - - operations = [ - migrations.AddField( - model_name='feedback', - name='slug', - field=models.SlugField(default=0), - ), - ] diff --git a/core/migrations/0008_auto_20170304_1612.py b/core/migrations/0008_auto_20170304_1612.py deleted file mode 100644 index c244e8a3affaa9da478db5bbae9f271b685e50b6..0000000000000000000000000000000000000000 --- a/core/migrations/0008_auto_20170304_1612.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-04 16:12 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0007_feedback_slug'), - ] - - operations = [ - migrations.AlterField( - model_name='feedback', - name='slug', - field=models.SlugField(blank=True), - ), - ] diff --git a/core/migrations/0009_auto_20170304_1614.py b/core/migrations/0009_auto_20170304_1614.py deleted file mode 100644 index f998c6653b13f7923d92543616567d8062332020..0000000000000000000000000000000000000000 --- a/core/migrations/0009_auto_20170304_1614.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-04 16:14 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0008_auto_20170304_1612'), - ] - - operations = [ - migrations.AlterField( - model_name='feedback', - name='slug', - field=models.SlugField(editable=False), - ), - ] diff --git a/core/migrations/0010_auto_20170304_1741.py b/core/migrations/0010_auto_20170304_1741.py deleted file mode 100644 index d1868e2b2baafcfa52d8c68188ace4924d2afcc1..0000000000000000000000000000000000000000 --- a/core/migrations/0010_auto_20170304_1741.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-04 17:41 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0009_auto_20170304_1614'), - ] - - operations = [ - migrations.AlterField( - model_name='submission', - name='student', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Student'), - ), - ] diff --git a/core/migrations/0011_auto_20170306_1327.py b/core/migrations/0011_auto_20170306_1327.py deleted file mode 100644 index 8527f5632e55664c7459756fa5edd52b23e1be19..0000000000000000000000000000000000000000 --- a/core/migrations/0011_auto_20170306_1327.py +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-06 13:27 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0010_auto_20170304_1741'), - ] - - operations = [ - migrations.CreateModel( - name='SubmissionStatus', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('status', models.CharField(choices=[('NF', 'NO_FEEDBACK'), ('CP', 'CORRECTION IN PROGRESS'), ('FL', 'FEEDBACK_LIMIT_REACHED'), ('RE', 'REVIEWED')], default='NF', max_length=2)), - ('feedback_counter', models.PositiveIntegerField(default=0, editable=False)), - ('final_feedback', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.Feedback')), - ], - ), - migrations.RemoveField( - model_name='submission', - name='final_feedback', - ), - migrations.AddField( - model_name='submissionstatus', - name='submission', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='core.Submission'), - ), - ] diff --git a/core/migrations/0012_auto_20170306_1450.py b/core/migrations/0012_auto_20170306_1450.py deleted file mode 100644 index 40238686ed6246246eee5b4ce3c8db5da6e3ee41..0000000000000000000000000000000000000000 --- a/core/migrations/0012_auto_20170306_1450.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-06 14:50 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0011_auto_20170306_1327'), - ] - - operations = [ - migrations.AlterField( - model_name='submissionstatus', - name='status', - field=models.CharField(choices=[('R', 'READY'), ('CP', 'CORRECTION_IN_PROGRESS'), ('FL', 'FEEDBACK_LIMIT_REACHED'), ('RE', 'REVIEWED')], default=('R', 'READY'), max_length=2), - ), - ] diff --git a/core/migrations/0013_auto_20170306_1452.py b/core/migrations/0013_auto_20170306_1452.py deleted file mode 100644 index f3c20ee56a4f5b8a7b69666ac3a0928e59abd8ce..0000000000000000000000000000000000000000 --- a/core/migrations/0013_auto_20170306_1452.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-06 14:52 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0012_auto_20170306_1450'), - ] - - operations = [ - migrations.AlterModelOptions( - name='submissionstatus', - options={'verbose_name': 'Submission Status', 'verbose_name_plural': 'Submission Status Set'}, - ), - ] diff --git a/core/migrations/0014_auto_20170306_1504.py b/core/migrations/0014_auto_20170306_1504.py deleted file mode 100644 index 4e58b7f624977884f53313ce973fd6bf692ace2d..0000000000000000000000000000000000000000 --- a/core/migrations/0014_auto_20170306_1504.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-06 15:04 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0013_auto_20170306_1452'), - ] - - operations = [ - migrations.RemoveField( - model_name='submissiontype', - name='type_id', - ), - migrations.AddField( - model_name='submissiontype', - name='id', - field=models.AutoField(auto_created=True, default=123, primary_key=True, serialize=False, verbose_name='ID'), - preserve_default=False, - ), - ] diff --git a/core/migrations/0015_auto_20170306_1525.py b/core/migrations/0015_auto_20170306_1525.py deleted file mode 100644 index a46ff49558dc317c104762d88241405315690e4d..0000000000000000000000000000000000000000 --- a/core/migrations/0015_auto_20170306_1525.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-06 15:25 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0014_auto_20170306_1504'), - ] - - operations = [ - migrations.AlterModelOptions( - name='student', - options={'verbose_name': 'Student', 'verbose_name_plural': 'Student Set'}, - ), - migrations.AlterModelOptions( - name='submission', - options={'verbose_name': 'Submission', 'verbose_name_plural': 'Submission Set'}, - ), - migrations.AlterModelOptions( - name='submissionstatus', - options={'verbose_name': 'Submission Status', 'verbose_name_plural': 'SubmissionStatus Set'}, - ), - migrations.AlterModelOptions( - name='submissiontype', - options={'verbose_name': 'SubmissionType', 'verbose_name_plural': 'SubmissionType Set'}, - ), - migrations.RemoveField( - model_name='submissionstatus', - name='submission', - ), - migrations.AddField( - model_name='submission', - name='submission_status', - field=models.OneToOneField(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.SubmissionStatus'), - ), - ] diff --git a/core/migrations/0016_auto_20170306_1535.py b/core/migrations/0016_auto_20170306_1535.py deleted file mode 100644 index 8af723801bfe0ee4f5780200aeeba51420198670..0000000000000000000000000000000000000000 --- a/core/migrations/0016_auto_20170306_1535.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-06 15:35 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0015_auto_20170306_1525'), - ] - - operations = [ - migrations.AlterField( - model_name='submission', - name='submission_status', - field=models.OneToOneField(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='submission', to='core.SubmissionStatus'), - ), - ] diff --git a/core/migrations/0017_auto_20170306_1550.py b/core/migrations/0017_auto_20170306_1550.py deleted file mode 100644 index 3d962950c26f6d92192a13e6296699c31e9ef4a1..0000000000000000000000000000000000000000 --- a/core/migrations/0017_auto_20170306_1550.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-06 15:50 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0016_auto_20170306_1535'), - ] - - operations = [ - migrations.AlterField( - model_name='submissionstatus', - name='feedback_counter', - field=models.PositiveIntegerField(default=0), - ), - migrations.AlterField( - model_name='submissionstatus', - name='status', - field=models.CharField(choices=[('R', 'READY'), ('CP', 'CORRECTION_IN_PROGRESS'), ('FL', 'FEEDBACK_LIMIT_REACHED'), ('RE', 'REVIEWED')], default='R', max_length=2), - ), - ] diff --git a/core/migrations/0018_auto_20170306_1605.py b/core/migrations/0018_auto_20170306_1605.py deleted file mode 100644 index 9e1cbd3cae6e76fe49104d395a147790cd68ac0b..0000000000000000000000000000000000000000 --- a/core/migrations/0018_auto_20170306_1605.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-06 16:05 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0017_auto_20170306_1550'), - ] - - operations = [ - migrations.RenameField( - model_name='submissiontype', - old_name='correction_guideline', - new_name='guideline', - ), - migrations.AlterField( - model_name='submissionstatus', - name='status', - field=models.PositiveIntegerField(choices=[(0, 'READY'), (1, 'IN_PROGRESS'), (2, 'LIMIT_REACHED'), (3, 'REVIEWED')], default=0), - ), - ] diff --git a/core/migrations/0019_auto_20170307_1735.py b/core/migrations/0019_auto_20170307_1735.py deleted file mode 100644 index 46804c6b343ece39a415ccd9f124cf6084220097..0000000000000000000000000000000000000000 --- a/core/migrations/0019_auto_20170307_1735.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-07 17:35 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0018_auto_20170306_1605'), - ] - - operations = [ - migrations.RenameField( - model_name='submission', - old_name='submission_status', - new_name='status', - ), - migrations.RenameField( - model_name='submission', - old_name='submission_text', - new_name='text', - ), - migrations.RenameField( - model_name='submission', - old_name='submission_type', - new_name='type', - ), - migrations.RenameField( - model_name='submissiontype', - old_name='correct_solution', - new_name='solution', - ), - migrations.AlterField( - model_name='submissionstatus', - name='status', - field=models.PositiveIntegerField(choices=[(0, 'READY'), (1, 'IN_PROGRESS'), (2, 'LIMIT_REACHED')], default=0), - ), - ] diff --git a/core/migrations/0020_auto_20170307_2031.py b/core/migrations/0020_auto_20170307_2031.py deleted file mode 100644 index ce0a33eb3f15ad2c02f44d553267cb1ab0b747fc..0000000000000000000000000000000000000000 --- a/core/migrations/0020_auto_20170307_2031.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-07 20:31 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0019_auto_20170307_1735'), - ] - - operations = [ - migrations.AlterField( - model_name='feedback', - name='slug', - field=models.SlugField(editable=False, unique=True), - ), - ] diff --git a/core/migrations/0021_auto_20170307_2122.py b/core/migrations/0021_auto_20170307_2122.py deleted file mode 100644 index 1c92e01aef6fb4d23183555598c308ea4a0068db..0000000000000000000000000000000000000000 --- a/core/migrations/0021_auto_20170307_2122.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-07 21:22 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0020_auto_20170307_2031'), - ] - - operations = [ - migrations.RemoveField( - model_name='submissionstatus', - name='feedback_counter', - ), - migrations.AlterField( - model_name='feedback', - name='of_submission', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feedback_list', to='core.Submission'), - ), - ] diff --git a/core/migrations/0022_auto_20170308_1439.py b/core/migrations/0022_auto_20170308_1439.py deleted file mode 100644 index c67c8c74a65b476c3e85449bcb036cd5dfcb5bf9..0000000000000000000000000000000000000000 --- a/core/migrations/0022_auto_20170308_1439.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-08 14:39 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0021_auto_20170307_2122'), - ] - - operations = [ - migrations.AddField( - model_name='feedback', - name='final', - field=models.BooleanField(default=False), - ), - migrations.AlterField( - model_name='submissionstatus', - name='status', - field=models.PositiveIntegerField(choices=[(0, 'READY'), (1, 'LIMIT_REACHED')], default=0), - ), - ] diff --git a/core/migrations/0023_auto_20170310_1422.py b/core/migrations/0023_auto_20170310_1422.py deleted file mode 100644 index 0c08410bad871330607e950775528e90665eeba6..0000000000000000000000000000000000000000 --- a/core/migrations/0023_auto_20170310_1422.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-10 14:22 -from __future__ import unicode_literals - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0022_auto_20170308_1439'), - ] - - operations = [ - migrations.AddField( - model_name='feedback', - name='max_score', - field=models.PositiveIntegerField(default=1000, editable=False), - ), - migrations.AlterField( - model_name='feedback', - name='score', - field=models.PositiveIntegerField(default=0, validators=[django.core.validators.MaxValueValidator(models.PositiveIntegerField(default=1000, editable=False)), django.core.validators.MinValueValidator(0)]), - ), - ] diff --git a/core/migrations/0024_auto_20170310_1502.py b/core/migrations/0024_auto_20170310_1502.py deleted file mode 100644 index f3df1f31f76b0c693862306af86ca99c6fe1a09f..0000000000000000000000000000000000000000 --- a/core/migrations/0024_auto_20170310_1502.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-10 15:02 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0023_auto_20170310_1422'), - ] - - operations = [ - migrations.RemoveField( - model_name='feedback', - name='max_score', - ), - migrations.AlterField( - model_name='feedback', - name='score', - field=models.PositiveIntegerField(default=0), - ), - ] diff --git a/core/migrations/0025_auto_20170311_1637.py b/core/migrations/0025_auto_20170311_1637.py deleted file mode 100644 index c9aeac279c3621da4eea53559708df2555bc11b9..0000000000000000000000000000000000000000 --- a/core/migrations/0025_auto_20170311_1637.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-11 16:37 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0024_auto_20170310_1502'), - ] - - operations = [ - migrations.RemoveField( - model_name='submissionstatus', - name='final_feedback', - ), - migrations.AddField( - model_name='submission', - name='final_feedback', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.Feedback'), - ), - migrations.AddField( - model_name='submission', - name='slug', - field=models.SlugField(default=23232323, editable=False, unique=True), - preserve_default=False, - ), - ] diff --git a/core/migrations/0026_submission_seen.py b/core/migrations/0026_submission_seen.py deleted file mode 100644 index 1cadbec022bbcef6c59a4b1e04a10e302a80d96c..0000000000000000000000000000000000000000 --- a/core/migrations/0026_submission_seen.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-11 16:56 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0025_auto_20170311_1637'), - ] - - operations = [ - migrations.AddField( - model_name='submission', - name='seen', - field=models.BooleanField(default=False), - ), - ] diff --git a/core/migrations/0028_auto_20170314_1726.py b/core/migrations/0028_auto_20170314_1726.py deleted file mode 100644 index 3993e2d96e216708709698ac0e40e168613f3d4c..0000000000000000000000000000000000000000 --- a/core/migrations/0028_auto_20170314_1726.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-14 17:26 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0027_submissiontype_description'), - ] - - operations = [ - migrations.RenameField( - model_name='submissiontype', - old_name='description', - new_name='correction_guideline', - ), - migrations.RenameField( - model_name='submissiontype', - old_name='guideline', - new_name='possible_solution', - ), - migrations.RenameField( - model_name='submissiontype', - old_name='solution', - new_name='task_description', - ), - ] diff --git a/core/migrations/0029_feedback_empty.py b/core/migrations/0029_feedback_empty.py deleted file mode 100644 index c691b2a64ff3201eee3a5d72330254114c8b8c24..0000000000000000000000000000000000000000 --- a/core/migrations/0029_feedback_empty.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-15 13:48 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0028_auto_20170314_1726'), - ] - - operations = [ - migrations.AddField( - model_name='feedback', - name='empty', - field=models.BooleanField(default=True), - ), - ] diff --git a/core/migrations/0030_auto_20170315_1444.py b/core/migrations/0030_auto_20170315_1444.py deleted file mode 100644 index bbc48683245f879cec13cf2223adf49b84ba7557..0000000000000000000000000000000000000000 --- a/core/migrations/0030_auto_20170315_1444.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-15 14:44 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('core', '0029_feedback_empty'), - ] - - operations = [ - migrations.RemoveField( - model_name='feedback', - name='of_reviewer', - ), - migrations.AddField( - model_name='feedback', - name='of_reviewer', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reviewed_submissions', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/core/migrations/0031_auto_20170315_1603.py b/core/migrations/0031_auto_20170315_1603.py deleted file mode 100644 index 0821ea8b7fbefc4753be9a6fd0346b5b5db4a176..0000000000000000000000000000000000000000 --- a/core/migrations/0031_auto_20170315_1603.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-15 16:03 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0030_auto_20170315_1444'), - ] - - operations = [ - migrations.RemoveField( - model_name='submission', - name='final_feedback', - ), - migrations.AlterField( - model_name='feedback', - name='of_submission', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feedback', to='core.Submission'), - ), - ] diff --git a/core/migrations/0032_auto_20170315_1609.py b/core/migrations/0032_auto_20170315_1609.py deleted file mode 100644 index 7842a7edc5e805b937f2543791edbfcff6bfc7fb..0000000000000000000000000000000000000000 --- a/core/migrations/0032_auto_20170315_1609.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-15 16:09 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0031_auto_20170315_1603'), - ] - - operations = [ - migrations.AddField( - model_name='submission', - name='final_feedback', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.Feedback'), - ), - migrations.AlterField( - model_name='feedback', - name='of_submission', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feedback_list', to='core.Submission'), - ), - ] diff --git a/core/migrations/0033_auto_20170321_2128.py b/core/migrations/0033_auto_20170321_2128.py deleted file mode 100644 index 7b593a580cedbb0c28639ad7b5260d5b17210cd1..0000000000000000000000000000000000000000 --- a/core/migrations/0033_auto_20170321_2128.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-21 21:28 -from __future__ import unicode_literals - -import core.models -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0032_auto_20170315_1609'), - ] - - operations = [ - migrations.AddField( - model_name='submissiontype', - name='slug', - field=models.SlugField(default=core.models.random_slug, editable=False, unique=True), - ), - migrations.AlterField( - model_name='feedback', - name='slug', - field=models.SlugField(default=core.models.random_slug, editable=False, unique=True), - ), - migrations.AlterField( - model_name='submission', - name='slug', - field=models.SlugField(default=core.models.random_slug, editable=False, unique=True), - ), - ] diff --git a/core/migrations/0034_auto_20170322_1304.py b/core/migrations/0034_auto_20170322_1304.py deleted file mode 100644 index 181986053bf9d7380272184c80fabf6f61a28beb..0000000000000000000000000000000000000000 --- a/core/migrations/0034_auto_20170322_1304.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-03-22 13:04 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0033_auto_20170321_2128'), - ] - - operations = [ - migrations.RemoveField( - model_name='submission', - name='status', - ), - migrations.DeleteModel( - name='SubmissionStatus', - ), - ] diff --git a/core/models.py b/core/models.py index 89f782d19b89880780225bf1c2901eba3a7490f6..824a5f76971f01978c961c00ded335e479f35ad3 100644 --- a/core/models.py +++ b/core/models.py @@ -97,14 +97,13 @@ class Submission(models.Model): if unfinished: return - ready = cls.objects.annotate(Count('feedback_list')).filter( feedback_list__count__lt=MAX_FEEDBACK_PER_SUBMISSION ) # we do not want this tutor to correct the same submission twice if type_slug: - ready = cls.objects.filter(type__slug=type_slug) + ready = ready.filter(type__slug=type_slug) ready = ready.exclude(feedback_list__of_tutor=tutor) if not ready: return diff --git a/core/views.py b/core/views.py index f243de00faef9f0bce4010d6e84fa2aebcc7583e..fa1ee4f6630284eb0ad5d5eff62a22dc8c3603a4 100644 --- a/core/views.py +++ b/core/views.py @@ -1,35 +1,14 @@ from django.contrib.auth import authenticate, login, logout -from django.contrib.auth.decorators import login_required, user_passes_test +from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User -from django.contrib import messages -from django.http import Http404, HttpResponse, HttpResponseRedirect +from django.db.models import Count +from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import render from django.urls import reverse -from django.db.models import Count -from django.utils.decorators import method_decorator -from django.views.generic import DetailView -from django.views.generic.edit import UpdateView -from core.forms import FeedbackForm +from core.custom_annotations import group_required, in_groups from core.models import Feedback, Submission, SubmissionType -from core.grady_speak import grady_says - -from random import choice - -# Create your views here. - - -def in_groups(user, group_list): - return bool(user.groups.filter(name__in=group_list)) or user.is_superuser - - -def group_required(*group_names): - """Requires user membership in at least one of the groups passed in.""" - def _in_groups(u): - if u.is_authenticated(): - return in_groups(u, group_names) - return user_passes_test(_in_groups) - +from core.viewset import * def index(request): context = { @@ -86,7 +65,7 @@ def tutor_view(request): 'submission_type_list': SubmissionType.objects.annotate( Count('submissions__feedback_list')).annotate( Count('submissions') - ).all(), + ).all(), 'feedback_list': Feedback.objects.filter(of_tutor=request.user), } return render(request, 'core/tutor_startpage.html', context) @@ -111,91 +90,3 @@ def reviewer_view(request): return render(request, 'core/reviewer_startpage.html', context) -@group_required('Tutors') -def create_feedback(request, type_slug=None): - # assign does nothing if tutor has unfinished feedback - Submission.assign_tutor(request.user, type_slug) - feedback = Feedback.tutor_unfinished_feedback(request.user) - if not feedback: - if type_slug: - messages.info(request, "No more submissions of this type available.") - else: - messages.success(request, "Well done! There is no more work to do.") - return HttpResponseRedirect(reverse('start')) - return HttpResponseRedirect(reverse('FeedbackEdit', args=(feedback.slug,))) - - -@group_required('Tutors', 'Reviewers') -def delete_feedback(request, feedback_slug): - """ Hook to ensure object is owned by request.user. """ - instance = Feedback.objects.get(slug=feedback_slug) - if instance.of_tutor != request.user and not in_groups(request.user, ('Reviewers', )): - raise Http404 - instance.delete() - return HttpResponseRedirect(reverse('start')) - - -@group_required('Reviewers') -def markfinal_feedback(request, feedback_slug): - instance = Feedback.objects.get(slug=feedback_slug) - instance.finalize_feedback(request.user) - return HttpResponseRedirect(reverse('start')) - - -@group_required('Reviewers') -def markunfinal_feedback(request, feedback_slug): - instance = Feedback.objects.get(slug=feedback_slug) - instance.unfinalize_feedback() - return HttpResponseRedirect(reverse('start')) - - -class FeedbackEdit(UpdateView): - - """docstring for FeedbackCreate""" - - form_class = FeedbackForm - template_name = 'core/feedback_form.html' - success_url = '/start/' - - @method_decorator(group_required('Tutors', 'Reviewers')) - def dispatch(self, *args, **kwargs): - return super(FeedbackEdit, self).dispatch(*args, **kwargs) - - def get_object(self): - instance = Feedback.objects.get(slug=self.kwargs['feedback_slug']) - if instance.of_tutor != self.request.user and not in_groups(self.request.user, ('Reviewers', )): - raise Http404 - return instance - - def form_valid(self, form): - """ - If the form is valid, redirect to the supplied URL. - """ - if form.is_valid(): - form.instance.empty = False - form.save() - if 'Next' in self.request.POST['update']: - return HttpResponseRedirect(reverse('CreateFeedbackForType', args=(form.instance.of_submission.type.slug,))) - return HttpResponseRedirect(self.get_success_url()) - - def get_context_data(self, **kwargs): - context = super(FeedbackEdit, self).get_context_data(**kwargs) - context['grady_says'] = choice(grady_says) - return context - - -class SubmissionView(DetailView): - - template_name = 'core/submission_view.html' - model = Submission - - @method_decorator(group_required('Reviewers', 'Students')) - def dispatch(self, *args, **kwargs): - return super(SubmissionView, self).dispatch(*args, **kwargs) - - def get_object(self): - obj = Submission.objects.get(slug=self.kwargs['slug']) - if obj.final_feedback: - obj.seen = True - obj.save() - return obj diff --git a/core/viewset/__init__.py b/core/viewset/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..fa4ec8df86197e56279e0429987a3c089ba55630 --- /dev/null +++ b/core/viewset/__init__.py @@ -0,0 +1,2 @@ +from .feedback import * +from .submission import * diff --git a/core/viewset/feedback.py b/core/viewset/feedback.py new file mode 100644 index 0000000000000000000000000000000000000000..554321eda0bafc3b66da52ecff044eefc9f029b5 --- /dev/null +++ b/core/viewset/feedback.py @@ -0,0 +1,87 @@ +from random import choice + +from django.contrib import messages +from django.http import Http404, HttpResponseRedirect +from django.urls import reverse +from django.utils.decorators import method_decorator +from django.views.generic.edit import UpdateView + +from core.custom_annotations import group_required, in_groups +from core.forms import FeedbackForm +from core.grady_speak import grady_says +from core.models import Feedback, Submission, SubmissionType + + +@group_required('Tutors') +def create_feedback(request, type_slug=None): + # assign does nothing if tutor has unfinished feedback + Submission.assign_tutor(request.user, type_slug) + feedback = Feedback.tutor_unfinished_feedback(request.user) + if not feedback: + if type_slug: + messages.info(request, "No more submissions of type '%s' available." % + SubmissionType.objects.get(slug=type_slug)) + else: + messages.success( + request, "Well done! There is no more work to do.") + return HttpResponseRedirect(reverse('start')) + return HttpResponseRedirect(reverse('FeedbackEdit', args=(feedback.slug,))) + + +@group_required('Tutors', 'Reviewers') +def delete_feedback(request, feedback_slug): + """ Hook to ensure object is owned by request.user. """ + instance = Feedback.objects.get(slug=feedback_slug) + if instance.of_tutor != request.user and not in_groups(request.user, ('Reviewers', )): + raise Http404 + instance.delete() + return HttpResponseRedirect(reverse('start')) + + +@group_required('Reviewers') +def markfinal_feedback(request, feedback_slug): + instance = Feedback.objects.get(slug=feedback_slug) + instance.finalize_feedback(request.user) + return HttpResponseRedirect(reverse('start')) + + +@group_required('Reviewers') +def markunfinal_feedback(request, feedback_slug): + instance = Feedback.objects.get(slug=feedback_slug) + instance.unfinalize_feedback() + return HttpResponseRedirect(reverse('start')) + + +class FeedbackEdit(UpdateView): + + """docstring for FeedbackCreate""" + + form_class = FeedbackForm + template_name = 'core/feedback_form.html' + success_url = '/start/' + + @method_decorator(group_required('Tutors', 'Reviewers')) + def dispatch(self, *args, **kwargs): + return super(FeedbackEdit, self).dispatch(*args, **kwargs) + + def get_object(self): + instance = Feedback.objects.get(slug=self.kwargs['feedback_slug']) + if instance.of_tutor != self.request.user and not in_groups(self.request.user, ('Reviewers', )): + raise Http404 + return instance + + def form_valid(self, form): + """ + If the form is valid, redirect to the supplied URL. + """ + if form.is_valid(): + form.instance.empty = False + form.save() + if 'Next' in self.request.POST['update']: + return HttpResponseRedirect(reverse('CreateFeedbackForType', args=(form.instance.of_submission.type.slug,))) + return HttpResponseRedirect(self.get_success_url()) + + def get_context_data(self, **kwargs): + context = super(FeedbackEdit, self).get_context_data(**kwargs) + context['grady_says'] = choice(grady_says) + return context diff --git a/core/viewset/submission.py b/core/viewset/submission.py new file mode 100644 index 0000000000000000000000000000000000000000..129e1f85dec7c845ff5a28ec47538ab50fe23cce --- /dev/null +++ b/core/viewset/submission.py @@ -0,0 +1,22 @@ +from django.utils.decorators import method_decorator +from django.views.generic import DetailView + +from core.custom_annotations import group_required +from core.models import Submission + + +class SubmissionView(DetailView): + + template_name = 'core/submission_view.html' + model = Submission + + @method_decorator(group_required('Reviewers', 'Students')) + def dispatch(self, *args, **kwargs): + return super(SubmissionView, self).dispatch(*args, **kwargs) + + def get_object(self): + obj = Submission.objects.get(slug=self.kwargs['slug']) + if obj.final_feedback: + obj.seen = True + obj.save() + return obj