From b3f5721f3cf4225902000f2f76e5138135383792 Mon Sep 17 00:00:00 2001 From: prathamesh Date: Thu, 8 Feb 2018 14:29:38 +0530 Subject: Add weightage for Quiz and Create Grading System App App Name: grades Grading System provides with the grade for a given value. It contains different grade ranges. Has its own default grading system. Allows you to modify and add grading system wth grade ranges. To be done: - Need to add README - Good UI - There are fields like can_be_used and order in models for future use. - More tests App name: Yaksh Now every quiz has a default weightage of 100%, can be changed. An aggregate is calculated for a given course. Using grades app a grade is provide to the aggregate value. --- grades/__init__.py | 0 grades/admin.py | 9 +++ grades/apps.py | 5 ++ grades/forms.py | 13 ++++ grades/migrations/0001_initial.py | 45 ++++++++++++ grades/migrations/__init__.py | 0 grades/migrations/default_grading_system.py | 36 ++++++++++ grades/models.py | 49 +++++++++++++ grades/templates/add_grades.html | 28 ++++++++ grades/templates/grading_systems.html | 17 +++++ grades/tests/test_models.py | 27 +++++++ grades/tests/test_views.py | 106 ++++++++++++++++++++++++++++ grades/urls.py | 10 +++ grades/views.py | 44 ++++++++++++ 14 files changed, 389 insertions(+) create mode 100644 grades/__init__.py create mode 100644 grades/admin.py create mode 100644 grades/apps.py create mode 100644 grades/forms.py create mode 100644 grades/migrations/0001_initial.py create mode 100644 grades/migrations/__init__.py create mode 100644 grades/migrations/default_grading_system.py create mode 100644 grades/models.py create mode 100644 grades/templates/add_grades.html create mode 100644 grades/templates/grading_systems.html create mode 100644 grades/tests/test_models.py create mode 100644 grades/tests/test_views.py create mode 100644 grades/urls.py create mode 100644 grades/views.py (limited to 'grades') diff --git a/grades/__init__.py b/grades/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/grades/admin.py b/grades/admin.py new file mode 100644 index 0000000..ab38f6b --- /dev/null +++ b/grades/admin.py @@ -0,0 +1,9 @@ +from django.contrib import admin +from grades.models import GradingSystem, GradeRange + +# Register your models here. +class GradingSystemAdmin(admin.ModelAdmin): + readonly_fields = ('creator',) + +admin.site.register(GradingSystem, GradingSystemAdmin) +admin.site.register(GradeRange) diff --git a/grades/apps.py b/grades/apps.py new file mode 100644 index 0000000..6d0985e --- /dev/null +++ b/grades/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class GradesConfig(AppConfig): + name = 'grades' diff --git a/grades/forms.py b/grades/forms.py new file mode 100644 index 0000000..f8c800a --- /dev/null +++ b/grades/forms.py @@ -0,0 +1,13 @@ +from grades.models import GradingSystem +from django import forms + +class GradingSystemForm(forms.ModelForm): + def __init__(self, *args, ** kwargs): + super(GradingSystemForm, self).__init__(*args, **kwargs) + system = getattr(self, 'instance', None) + if system.name == 'default': + self.fields['name'].widget.attrs['readonly'] = True + + class Meta: + model = GradingSystem + fields = ['name', 'description', 'can_be_used'] diff --git a/grades/migrations/0001_initial.py b/grades/migrations/0001_initial.py new file mode 100644 index 0000000..65d711e --- /dev/null +++ b/grades/migrations/0001_initial.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.5 on 2018-02-02 06:20 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='GradeRange', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('order', models.IntegerField(default=0)), + ('lower_limit', models.FloatField()), + ('upper_limit', models.FloatField()), + ('grade', models.CharField(max_length=10)), + ('description', models.CharField(blank=True, max_length=127, null=True)), + ], + ), + migrations.CreateModel( + name='GradingSystem', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, unique=True)), + ('description', models.TextField(default='About the grading system!')), + ('can_be_used', models.BooleanField(default=False)), + ('creator', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AddField( + model_name='graderange', + name='system', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='grades.GradingSystem'), + ), + ] diff --git a/grades/migrations/__init__.py b/grades/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/grades/migrations/default_grading_system.py b/grades/migrations/default_grading_system.py new file mode 100644 index 0000000..1629d29 --- /dev/null +++ b/grades/migrations/default_grading_system.py @@ -0,0 +1,36 @@ +from django.db import migrations + +def create_default_system(apps, schema_editor): + GradingSystem = apps.get_model('grades', 'GradingSystem') + GradeRange = apps.get_model('grades', 'GradeRange') + db = schema_editor.connection.alias + + default_system = GradingSystem.objects.using(db).create(name='default', + can_be_used=True) + GradeRange.objects.using(db).create(system=default_system, order=1, lower_limit=0, + upper_limit=40, grade='F', description='Fail') + GradeRange.objects.using(db).create(system=default_system, order=2, lower_limit=40, + upper_limit=55, grade='P', description='Pass') + GradeRange.objects.using(db).create(system=default_system, order=3, lower_limit=55, + upper_limit=60, grade='C', description='Average') + GradeRange.objects.using(db).create(system=default_system, order=4, lower_limit=60, + upper_limit=75, grade='B', description='Satisfactory') + GradeRange.objects.using(db).create(system=default_system, order=5, lower_limit=75, + upper_limit=90, grade='A', description='Good') + GradeRange.objects.using(db).create(system=default_system, order=6, lower_limit=90, + upper_limit=101, grade='A+', description='Excellent') + + +def delete_default_system(apps, schema_editor): + GradingSystem = apps.get_model('grades', 'GradingSystem') + GradeRange = apps.get_model('grades', 'GradeRange') + db = schema_editor.connection.alias + + default_system = GradingSystem.objects.using(db).get(creator=None) + GradeRange.object.using(db).filter(system=default_system).delete() + default_system.delete() + + +class Migration(migrations.Migration): + dependencies = [('grades', '0001_initial'),] + operations = [migrations.RunPython(create_default_system, delete_default_system),] diff --git a/grades/models.py b/grades/models.py new file mode 100644 index 0000000..33895bb --- /dev/null +++ b/grades/models.py @@ -0,0 +1,49 @@ +from django.db import models +from django.contrib.auth.models import User + +# Create your models here. + +class GradingSystem(models.Model): + name = models.CharField(max_length=255, unique=True) + description = models.TextField(default='About the grading system!') + can_be_used = models.BooleanField(default=False) + creator = models.ForeignKey(User, null=True, blank=True) + + def get_grade(self, marks): + ranges = self.graderange_set.all() + lower_limits = ranges.values_list('lower_limit', flat=True) + upper_limits = ranges.values_list('upper_limit', flat=True) + lower_limit = self._get_lower_limit(marks, lower_limits) + upper_limit = self._get_upper_limit(marks, upper_limits) + grade_range = ranges.filter(lower_limit=lower_limit, + upper_limit=upper_limit).first() + if grade_range: + return grade_range.grade + + def _get_upper_limit(self, marks, upper_limits): + greater_than = [upper_limit for upper_limit in upper_limits + if upper_limit > marks] + if greater_than: + return min(greater_than, key=lambda x: x-marks) + + def _get_lower_limit(self, marks, lower_limits): + less_than = [] + for lower_limit in lower_limits: + if lower_limit == marks: + return lower_limit + if lower_limit < marks: + less_than.append(lower_limit) + if less_than: + return max(less_than, key=lambda x: x-marks) + + def __str__(self): + return self.name.title() + + +class GradeRange(models.Model): + system = models.ForeignKey(GradingSystem) + order = models.IntegerField(default=0) + lower_limit = models.FloatField() + upper_limit = models.FloatField() + grade = models.CharField(max_length=10) + description = models.CharField(max_length=127, null=True, blank=True) diff --git a/grades/templates/add_grades.html b/grades/templates/add_grades.html new file mode 100644 index 0000000..f2f0051 --- /dev/null +++ b/grades/templates/add_grades.html @@ -0,0 +1,28 @@ + + Back to Grading Systems +

Note: For grade range lower limit is inclusive and upper limit is exclusive

+{% if not system_id %} +
+{% else %} + +{% endif %} + {% csrf_token %} + + {{ grade_form }} +
+ {{ formset.management_form }} +
+ Grade Ranges +
+ {% for form in formset %} +
+ {{ form }} +
+
+ {% endfor %} + + + + +
+ diff --git a/grades/templates/grading_systems.html b/grades/templates/grading_systems.html new file mode 100644 index 0000000..143b037 --- /dev/null +++ b/grades/templates/grading_systems.html @@ -0,0 +1,17 @@ + + Default Grading System: + + My grading System: + {% if grading_systems %} + + {% else %} +

None. You can add one.

+ {% endif %} + Add a Grading System + diff --git a/grades/tests/test_models.py b/grades/tests/test_models.py new file mode 100644 index 0000000..89708e2 --- /dev/null +++ b/grades/tests/test_models.py @@ -0,0 +1,27 @@ +from django.test import TestCase +from grades.models import GradingSystem, GradeRange + +# Create your tests here. +class GradingSystemTestCase(TestCase): + def setUp(self): + GradingSystem.objects.create(name='unusable') + + def test_get_grade(self): + # Given + grading_system = GradingSystem.objects.get(name='default') + expected_grades = {0:'F', 31:'F', 49:'P', 55:'C', 60:'B', 80:'A', + 95:'A+', 100:'A+', 100.5:'A+', 101:None, 109:None} + for marks in expected_grades.keys(): + # When + grade = grading_system.get_grade(marks) + # Then + self.assertEqual(expected_grades.get(marks), grade) + + def test_grade_system_unusable(self): + # Given + grading_system = GradingSystem.objects.get(name='unusable') + # When + grade = grading_system.get_grade(29) + # Then + self.assertIsNone(grade) + diff --git a/grades/tests/test_views.py b/grades/tests/test_views.py new file mode 100644 index 0000000..2c29ae5 --- /dev/null +++ b/grades/tests/test_views.py @@ -0,0 +1,106 @@ +from django.test import TestCase, Client +from django.contrib.auth.models import User +from django.core.urlresolvers import reverse +from grades.models import GradingSystem + + +def setUpModule(): + user = User.objects.create_user(username='grades_user', + password='grades_user') + +def tearDownModule(): + User.objects.all().delete() + + +class GradeViewTest(TestCase): + def setUp(self): + self.client = Client() + + def tearDown(self): + self.client.logout() + + def test_grade_view(self): + # Given + # URL redirection due to no login credentials + status_code = 302 + # When + response = self.client.get(reverse('grades:grading_systems')) + # Then + self.assertEqual(response.status_code, status_code) + + # Given + # successful login and grading systems views + self.client.login(username='grades_user', password='grades_user') + status_code = 200 + # When + response = self.client.get(reverse('grades:grading_systems')) + # Then + self.assertEqual(response.status_code, status_code) + self.assertTemplateUsed(response, 'grading_systems.html') + + +class AddGradingSystemTest(TestCase): + def setUp(self): + self.client = Client() + + def tearDown(self): + self.client.logout() + + def test_add_grades_view(self): + # Given + status_code = 302 + # When + response = self.client.get(reverse('grades:add_grade')) + # Then + self.assertEqual(response.status_code, status_code) + + # Given + status_code = 200 + self.client.login(username='grades_user', password='grades_user') + # When + response = self.client.get(reverse('grades:add_grade')) + # Then + self.assertEqual(response.status_code, status_code) + self.assertTemplateUsed(response, 'add_grades.html') + + def test_add_grades_post(self): + # Given + self.client.login(username='grades_user', password='grades_user') + data = {'name': ['new_sys'], 'description': ['About the grading system!'], + 'graderange_set-MIN_NUM_FORMS': ['0'], + 'graderange_set-TOTAL_FORMS': ['0'], 'can_be_used': ['on'], + 'graderange_set-MAX_NUM_FORMS': ['1000'], 'add': ['Add'], + 'graderange_set-INITIAL_FORMS': ['0']} + # When + response = self.client.post(reverse('grades:add_grade'), data) + # Then + grading_systems = GradingSystem.objects.filter(name='new_sys') + self.assertEqual(len(grading_systems), 1) + + # Given + grading_system = grading_systems.first() + # When + ranges = grading_system.graderange_set.all() + # Then + self.assertEqual(len(ranges), 0) + + # Given + data = {'graderange_set-0-upper_limit': ['40'], + 'graderange_set-0-order': ['0'], + 'graderange_set-0-description': ['Fail'], + 'graderange_set-0-lower_limit': ['0'], + 'graderange_set-0-system': [''], 'name': ['new_sys'], + 'graderange_set-MIN_NUM_FORMS': ['0'], + 'graderange_set-TOTAL_FORMS': ['1'], 'can_be_used': ['on'], + 'graderange_set-MAX_NUM_FORMS': ['1000'], + 'graderange_set-0-id': [''], + 'description': ['About the grading system!'], + 'graderange_set-0-grade': ['F'], + 'graderange_set-INITIAL_FORMS': ['0'], 'save': ['Save']} + # When + response = self.client.post(reverse('grades:edit_grade', + kwargs={'system_id': 2}), data) + # Then + ranges = grading_system.graderange_set.all() + self.assertEqual(len(ranges), 1) + diff --git a/grades/urls.py b/grades/urls.py new file mode 100644 index 0000000..49276ba9 --- /dev/null +++ b/grades/urls.py @@ -0,0 +1,10 @@ +from django.conf.urls import url, patterns +from grades import views + +urlpatterns = [ + url(r'^$', views.grading_systems, name="grading_systems_home"), + url(r'^grading_systems/$', views.grading_systems, name="grading_systems"), + url(r'^add_grade/$', views.add_grading_system, name="add_grade"), + url(r'^add_grade/(?P\d+)/$', views.add_grading_system, + name="edit_grade"), +] diff --git a/grades/views.py b/grades/views.py new file mode 100644 index 0000000..86803c9 --- /dev/null +++ b/grades/views.py @@ -0,0 +1,44 @@ +from django.shortcuts import render +from django.contrib.auth.decorators import login_required +from django.forms import inlineformset_factory +from grades.forms import GradingSystemForm +from grades.models import GradingSystem, GradeRange + +# Create your views here. +@login_required +def grading_systems(request): + user = request.user + default_grading_system = GradingSystem.objects.get(name='default') + grading_systems = GradingSystem.objects.filter(creator=user).exclude( + name='default') + return render(request, 'grading_systems.html', {'default_grading_system': + default_grading_system, 'grading_systems': grading_systems}) + + +@login_required +def add_grading_system(request, system_id=None): + user = request.user + grading_system = None + if system_id is not None: + grading_system = GradingSystem.objects.get(id=system_id) + GradeRangeFormSet = inlineformset_factory(GradingSystem, GradeRange, + fields='__all__', extra=0) + grade_form = GradingSystemForm(instance=grading_system) + + if request.method == 'POST': + formset = GradeRangeFormSet(request.POST, instance=grading_system) + grade_form = GradingSystemForm(request.POST, instance=grading_system) + if grade_form.is_valid(): + system = grade_form.save(commit=False) + system.creator = user + system.save() + system_id = system.id + if formset.is_valid(): + formset.save() + if 'add' in request.POST: + GradeRangeFormSet = inlineformset_factory(GradingSystem, GradeRange, + fields='__all__', extra=1) + formset = GradeRangeFormSet(instance=grading_system) + + return render(request, 'add_grades.html', {'formset': formset, + 'grade_form': grade_form, "system_id": system_id}) -- cgit From 24bce890f07b6696ef1e910443a41a54840a6e90 Mon Sep 17 00:00:00 2001 From: prathamesh Date: Thu, 8 Feb 2018 15:16:22 +0530 Subject: Treat grades/tests as python package directory --- grades/tests/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 grades/tests/__init__.py (limited to 'grades') diff --git a/grades/tests/__init__.py b/grades/tests/__init__.py new file mode 100644 index 0000000..e69de29 -- cgit From f06a5d2ffbb1a06320935841a4ba24720e651985 Mon Sep 17 00:00:00 2001 From: prathamesh Date: Tue, 13 Feb 2018 12:48:19 +0530 Subject: Change default grading system behaviour Cannot edit default system. Code as per PEP8 standards. Updates grade after regrade or manual grading Field change from total marks to percentage Removed unused fields from grades app --- grades/admin.py | 2 +- grades/forms.py | 9 ++----- grades/migrations/0001_initial.py | 4 +--- grades/migrations/default_grading_system.py | 37 ++++++++++++++++------------- grades/models.py | 3 --- grades/templates/add_grades.html | 10 ++++---- grades/tests/test_models.py | 9 +++---- grades/tests/test_views.py | 11 ++++----- grades/views.py | 9 +++---- 9 files changed, 46 insertions(+), 48 deletions(-) (limited to 'grades') diff --git a/grades/admin.py b/grades/admin.py index ab38f6b..548791e 100644 --- a/grades/admin.py +++ b/grades/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin from grades.models import GradingSystem, GradeRange -# Register your models here. + class GradingSystemAdmin(admin.ModelAdmin): readonly_fields = ('creator',) diff --git a/grades/forms.py b/grades/forms.py index f8c800a..130659d 100644 --- a/grades/forms.py +++ b/grades/forms.py @@ -1,13 +1,8 @@ from grades.models import GradingSystem from django import forms -class GradingSystemForm(forms.ModelForm): - def __init__(self, *args, ** kwargs): - super(GradingSystemForm, self).__init__(*args, **kwargs) - system = getattr(self, 'instance', None) - if system.name == 'default': - self.fields['name'].widget.attrs['readonly'] = True +class GradingSystemForm(forms.ModelForm): class Meta: model = GradingSystem - fields = ['name', 'description', 'can_be_used'] + fields = ['name', 'description'] diff --git a/grades/migrations/0001_initial.py b/grades/migrations/0001_initial.py index 65d711e..04a3006 100644 --- a/grades/migrations/0001_initial.py +++ b/grades/migrations/0001_initial.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.9.5 on 2018-02-02 06:20 +# Generated by Django 1.9.5 on 2018-02-12 11:12 from __future__ import unicode_literals from django.conf import settings @@ -20,7 +20,6 @@ class Migration(migrations.Migration): name='GradeRange', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('order', models.IntegerField(default=0)), ('lower_limit', models.FloatField()), ('upper_limit', models.FloatField()), ('grade', models.CharField(max_length=10)), @@ -33,7 +32,6 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=255, unique=True)), ('description', models.TextField(default='About the grading system!')), - ('can_be_used', models.BooleanField(default=False)), ('creator', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], ), diff --git a/grades/migrations/default_grading_system.py b/grades/migrations/default_grading_system.py index 1629d29..85390d6 100644 --- a/grades/migrations/default_grading_system.py +++ b/grades/migrations/default_grading_system.py @@ -1,24 +1,28 @@ from django.db import migrations + def create_default_system(apps, schema_editor): GradingSystem = apps.get_model('grades', 'GradingSystem') GradeRange = apps.get_model('grades', 'GradeRange') db = schema_editor.connection.alias - default_system = GradingSystem.objects.using(db).create(name='default', - can_be_used=True) - GradeRange.objects.using(db).create(system=default_system, order=1, lower_limit=0, - upper_limit=40, grade='F', description='Fail') - GradeRange.objects.using(db).create(system=default_system, order=2, lower_limit=40, - upper_limit=55, grade='P', description='Pass') - GradeRange.objects.using(db).create(system=default_system, order=3, lower_limit=55, - upper_limit=60, grade='C', description='Average') - GradeRange.objects.using(db).create(system=default_system, order=4, lower_limit=60, - upper_limit=75, grade='B', description='Satisfactory') - GradeRange.objects.using(db).create(system=default_system, order=5, lower_limit=75, - upper_limit=90, grade='A', description='Good') - GradeRange.objects.using(db).create(system=default_system, order=6, lower_limit=90, - upper_limit=101, grade='A+', description='Excellent') + default_system = GradingSystem.objects.using(db).create(name='default') + + graderanges_objects = [ + GradeRange(system=default_system, lower_limit=0, upper_limit=40, + grade='F', description='Fail'), + GradeRange(system=default_system, lower_limit=40, upper_limit=55, + grade='P', description='Pass'), + GradeRange(system=default_system, lower_limit=55, upper_limit=60, + grade='C', description='Average'), + GradeRange(system=default_system, lower_limit=60, upper_limit=75, + grade='B', description='Satisfactory'), + GradeRange(system=default_system, lower_limit=75, upper_limit=90, + grade='A', description='Good'), + GradeRange(system=default_system, lower_limit=90, upper_limit=101, + grade='A+', description='Excellent') + ] + GradeRange.objects.using(db).bulk_create(graderanges_objects) def delete_default_system(apps, schema_editor): @@ -32,5 +36,6 @@ def delete_default_system(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [('grades', '0001_initial'),] - operations = [migrations.RunPython(create_default_system, delete_default_system),] + dependencies = [('grades', '0001_initial'), ] + operations = [migrations.RunPython(create_default_system, + delete_default_system), ] diff --git a/grades/models.py b/grades/models.py index 33895bb..fcea510 100644 --- a/grades/models.py +++ b/grades/models.py @@ -1,12 +1,10 @@ from django.db import models from django.contrib.auth.models import User -# Create your models here. class GradingSystem(models.Model): name = models.CharField(max_length=255, unique=True) description = models.TextField(default='About the grading system!') - can_be_used = models.BooleanField(default=False) creator = models.ForeignKey(User, null=True, blank=True) def get_grade(self, marks): @@ -42,7 +40,6 @@ class GradingSystem(models.Model): class GradeRange(models.Model): system = models.ForeignKey(GradingSystem) - order = models.IntegerField(default=0) lower_limit = models.FloatField() upper_limit = models.FloatField() grade = models.CharField(max_length=10) diff --git a/grades/templates/add_grades.html b/grades/templates/add_grades.html index f2f0051..1e4d29e 100644 --- a/grades/templates/add_grades.html +++ b/grades/templates/add_grades.html @@ -20,9 +20,11 @@
{% endfor %} - - - - + {% if not is_default %} + + + {% else %} +

Note: This is a default grading system. You cannot change this.

+ {% endif %} diff --git a/grades/tests/test_models.py b/grades/tests/test_models.py index 89708e2..f8d5c5c 100644 --- a/grades/tests/test_models.py +++ b/grades/tests/test_models.py @@ -1,7 +1,7 @@ from django.test import TestCase from grades.models import GradingSystem, GradeRange -# Create your tests here. + class GradingSystemTestCase(TestCase): def setUp(self): GradingSystem.objects.create(name='unusable') @@ -9,8 +9,9 @@ class GradingSystemTestCase(TestCase): def test_get_grade(self): # Given grading_system = GradingSystem.objects.get(name='default') - expected_grades = {0:'F', 31:'F', 49:'P', 55:'C', 60:'B', 80:'A', - 95:'A+', 100:'A+', 100.5:'A+', 101:None, 109:None} + expected_grades = {0: 'F', 31: 'F', 49: 'P', 55: 'C', 60: 'B', 80: 'A', + 95: 'A+', 100: 'A+', 100.5: 'A+', 101: None, + 109: None} for marks in expected_grades.keys(): # When grade = grading_system.get_grade(marks) @@ -19,9 +20,9 @@ class GradingSystemTestCase(TestCase): def test_grade_system_unusable(self): # Given + # System with out ranges grading_system = GradingSystem.objects.get(name='unusable') # When grade = grading_system.get_grade(29) # Then self.assertIsNone(grade) - diff --git a/grades/tests/test_views.py b/grades/tests/test_views.py index 2c29ae5..c944f03 100644 --- a/grades/tests/test_views.py +++ b/grades/tests/test_views.py @@ -6,7 +6,8 @@ from grades.models import GradingSystem def setUpModule(): user = User.objects.create_user(username='grades_user', - password='grades_user') + password='grades_user') + def tearDownModule(): User.objects.all().delete() @@ -66,9 +67,9 @@ class AddGradingSystemTest(TestCase): def test_add_grades_post(self): # Given self.client.login(username='grades_user', password='grades_user') - data = {'name': ['new_sys'], 'description': ['About the grading system!'], + data = {'name': ['new_sys'], 'description': ['About grading system!'], 'graderange_set-MIN_NUM_FORMS': ['0'], - 'graderange_set-TOTAL_FORMS': ['0'], 'can_be_used': ['on'], + 'graderange_set-TOTAL_FORMS': ['0'], 'graderange_set-MAX_NUM_FORMS': ['1000'], 'add': ['Add'], 'graderange_set-INITIAL_FORMS': ['0']} # When @@ -86,12 +87,11 @@ class AddGradingSystemTest(TestCase): # Given data = {'graderange_set-0-upper_limit': ['40'], - 'graderange_set-0-order': ['0'], 'graderange_set-0-description': ['Fail'], 'graderange_set-0-lower_limit': ['0'], 'graderange_set-0-system': [''], 'name': ['new_sys'], 'graderange_set-MIN_NUM_FORMS': ['0'], - 'graderange_set-TOTAL_FORMS': ['1'], 'can_be_used': ['on'], + 'graderange_set-TOTAL_FORMS': ['1'], 'graderange_set-MAX_NUM_FORMS': ['1000'], 'graderange_set-0-id': [''], 'description': ['About the grading system!'], @@ -103,4 +103,3 @@ class AddGradingSystemTest(TestCase): # Then ranges = grading_system.graderange_set.all() self.assertEqual(len(ranges), 1) - diff --git a/grades/views.py b/grades/views.py index 86803c9..10f9999 100644 --- a/grades/views.py +++ b/grades/views.py @@ -4,13 +4,12 @@ from django.forms import inlineformset_factory from grades.forms import GradingSystemForm from grades.models import GradingSystem, GradeRange -# Create your views here. + @login_required def grading_systems(request): user = request.user default_grading_system = GradingSystem.objects.get(name='default') - grading_systems = GradingSystem.objects.filter(creator=user).exclude( - name='default') + grading_systems = GradingSystem.objects.filter(creator=user) return render(request, 'grading_systems.html', {'default_grading_system': default_grading_system, 'grading_systems': grading_systems}) @@ -24,6 +23,7 @@ def add_grading_system(request, system_id=None): GradeRangeFormSet = inlineformset_factory(GradingSystem, GradeRange, fields='__all__', extra=0) grade_form = GradingSystemForm(instance=grading_system) + is_default = grading_system is not None and grading_system.name == 'default' if request.method == 'POST': formset = GradeRangeFormSet(request.POST, instance=grading_system) @@ -41,4 +41,5 @@ def add_grading_system(request, system_id=None): formset = GradeRangeFormSet(instance=grading_system) return render(request, 'add_grades.html', {'formset': formset, - 'grade_form': grade_form, "system_id": system_id}) + 'grade_form': grade_form, "system_id": system_id, + 'is_default': is_default}) -- cgit From 95f5f27c18380e2fb2f33526c467e822dd10c4d8 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 1 Mar 2018 18:56:13 +0530 Subject: Add basic UI for grading system --- grades/templates/add_grades.html | 12 ++++-- grades/templates/grading_systems.html | 80 +++++++++++++++++++++++++++++------ 2 files changed, 76 insertions(+), 16 deletions(-) (limited to 'grades') diff --git a/grades/templates/add_grades.html b/grades/templates/add_grades.html index 1e4d29e..e4ea915 100644 --- a/grades/templates/add_grades.html +++ b/grades/templates/add_grades.html @@ -1,13 +1,16 @@ +{% extends "manage.html" %} +{% block main %} - Back to Grading Systems + Back to Grading Systems

Note: For grade range lower limit is inclusive and upper limit is exclusive

+
{% if not system_id %}
{% else %} {% endif %} {% csrf_token %} - +
{{ grade_form }}
{{ formset.management_form }} @@ -21,10 +24,11 @@
{% endfor %} {% if not is_default %} - - + + {% else %}

Note: This is a default grading system. You cannot change this.

{% endif %}
+{% endblock %} diff --git a/grades/templates/grading_systems.html b/grades/templates/grading_systems.html index 143b037..baa5610 100644 --- a/grades/templates/grading_systems.html +++ b/grades/templates/grading_systems.html @@ -1,17 +1,73 @@ +{% extends "manage.html" %} +{% block main %} - Default Grading System: - - My grading System: - {% if grading_systems %} -