diff options
-rw-r--r-- | grades/admin.py | 2 | ||||
-rw-r--r-- | grades/forms.py | 9 | ||||
-rw-r--r-- | grades/migrations/0001_initial.py | 4 | ||||
-rw-r--r-- | grades/migrations/default_grading_system.py | 37 | ||||
-rw-r--r-- | grades/models.py | 3 | ||||
-rw-r--r-- | grades/templates/add_grades.html | 10 | ||||
-rw-r--r-- | grades/tests/test_models.py | 9 | ||||
-rw-r--r-- | grades/tests/test_views.py | 11 | ||||
-rw-r--r-- | grades/views.py | 9 | ||||
-rw-r--r-- | yaksh/models.py | 20 | ||||
-rw-r--r-- | yaksh/views.py | 23 |
11 files changed, 80 insertions, 57 deletions
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 @@ </div> <hr> {% endfor %} - - <input type="submit" id="add" name="add" value="Add"> - <input type="submit" id="save" name="save" value="Save"> - + {% if not is_default %} + <input type="submit" id="add" name="add" value="Add"> + <input type="submit" id="save" name="save" value="Save"> + {% else %} + <p><b>Note: This is a default grading system. You cannot change this.</b></p> + {% endif %} </form> </html> 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}) diff --git a/yaksh/models.py b/yaksh/models.py index f76feed..1ecb1f8 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -738,13 +738,22 @@ class CourseStatus(models.Model): course = models.ForeignKey(Course) user = models.ForeignKey(User) grade = models.CharField(max_length=255, null=True, blank=True) - total_marks = models.FloatField(default=0.0) + percentage = models.FloatField(default=0.0) + + def get_grade(self): + return self.grade def set_grade(self): - grade = self.course.grading_system.get_grade(self.total_marks) - self.grade = grade + if self.is_course_complete(): + self.calculate_percentage() + if self.course.grading_system is None: + grading_system = GradingSystem.objects.get(name='default') + else: + grading_system = self.course.grading_system + grade = grading_system.get_grade(self.percentage) + self.grade = grade - def calculate_total_marks(self): + def calculate_percentage(self): if self.is_course_complete(): quizzes = self.course.get_quizzes() total_weightage = 0 @@ -755,8 +764,7 @@ class CourseStatus(models.Model): quiz, self.user.id, self.course.id) out_of = quiz.questionpaper_set.first().total_marks sum += (marks/out_of)*quiz.weightage - self.total_marks = (sum/total_weightage)*100 - self.set_grade() + self.percentage = (sum/total_weightage)*100 def is_course_complete(self): diff --git a/yaksh/views.py b/yaksh/views.py index 30b454b..356c66e 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -1664,6 +1664,10 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None, 'comments_%d' % paper.question_paper.id, 'No comments') paper.save() + course_status = CourseStatus.objects.filter(course=course, user=user) + if course_status.exists(): + course_status.first().set_grade() + return my_render_to_response( 'yaksh/grade_user.html', context, context_instance=ci ) @@ -1919,14 +1923,27 @@ def regrade(request, course_id, question_id=None, answerpaper_id=None, answerpaper = get_object_or_404(AnswerPaper, pk=answerpaper_id) for question in answerpaper.questions.all(): details.append(answerpaper.regrade(question.id)) + course_status = CourseStatus.objects.filter(user=answerpaper.user, + course=answerpaper.course) + if course_status.exists(): + course_status.first().set_grade() if questionpaper_id is not None and question_id is not None: answerpapers = AnswerPaper.objects.filter(questions=question_id, question_paper_id=questionpaper_id, course_id=course_id) for answerpaper in answerpapers: details.append(answerpaper.regrade(question_id)) + course_status = CourseStatus.objects.filter(user=answerpaper.user, + course=answerpaper.course) + if course_status.exists(): + course_status.first().set_grade() if answerpaper_id is not None and question_id is not None: answerpaper = get_object_or_404(AnswerPaper, pk=answerpaper_id) details.append(answerpaper.regrade(question_id)) + course_status = CourseStatus.objects.filter(user=answerpaper.user, + course=answerpaper.course) + if course_status.exists(): + course_status.first().set_grade() + return grader(request, extra_context={'details': details}) @@ -2713,9 +2730,9 @@ def course_modules(request, course_id, msg=None): course_status = CourseStatus.objects.filter(course=course, user=user) if course_status.exists(): course_status = course_status.first() - if course_status.is_course_complete() and not course_status.grade: - course_status.calculate_total_marks() - context['grade'] = course_status.grade + if not course_status.grade: + course_status.set_grade() + context['grade'] = course_status.get_grade() return my_render_to_response('yaksh/course_modules.html', context) |