From 6478d43329aaedbb77127510bcfc64e7f7db84b4 Mon Sep 17 00:00:00 2001 From: Stu Young Date: Thu, 16 May 2019 11:02:36 -0400 Subject: [PATCH] incr-298 (#20606) * run python modernize * run isort * Split out handlers/apps into separate files. --- lms/djangoapps/course_goals/api.py | 8 +++-- lms/djangoapps/course_goals/apps.py | 20 ++++++++++++ lms/djangoapps/course_goals/handlers.py | 25 +++++++++++++++ .../course_goals/migrations/0001_initial.py | 1 + .../migrations/0002_auto_20171010_1129.py | 1 + lms/djangoapps/course_goals/models.py | 31 +++++-------------- lms/djangoapps/course_goals/tests/test_api.py | 8 +++-- lms/djangoapps/course_goals/urls.py | 2 ++ lms/djangoapps/course_goals/views.py | 9 +++--- lms/envs/common.py | 2 +- 10 files changed, 71 insertions(+), 36 deletions(-) create mode 100644 lms/djangoapps/course_goals/apps.py create mode 100644 lms/djangoapps/course_goals/handlers.py diff --git a/lms/djangoapps/course_goals/api.py b/lms/djangoapps/course_goals/api.py index 55f090f88a..6fcfd73c72 100644 --- a/lms/djangoapps/course_goals/api.py +++ b/lms/djangoapps/course_goals/api.py @@ -1,16 +1,18 @@ """ Course Goals Python API """ -import models -from six import text_type +from __future__ import absolute_import -from opaque_keys.edx.keys import CourseKey from django.conf import settings +from opaque_keys.edx.keys import CourseKey from rest_framework.reverse import reverse +from six import text_type from course_modes.models import CourseMode from openedx.features.course_experience import ENABLE_COURSE_GOALS +from . import models + def add_course_goal(user, course_id, goal_key): """ diff --git a/lms/djangoapps/course_goals/apps.py b/lms/djangoapps/course_goals/apps.py new file mode 100644 index 0000000000..122889be64 --- /dev/null +++ b/lms/djangoapps/course_goals/apps.py @@ -0,0 +1,20 @@ +""" +Course Goals Application Configuration + +Signal handlers are connected here. +""" + +from django.apps import AppConfig + + +class CourseGoalsConfig(AppConfig): + """ + Application Configuration for Course Goals. + """ + name = 'lms.djangoapps.course_goals' + + def ready(self): + """ + Connect signal handlers. + """ + from . import handlers # pylint: disable=unused-variable diff --git a/lms/djangoapps/course_goals/handlers.py b/lms/djangoapps/course_goals/handlers.py new file mode 100644 index 0000000000..ff1353a1cb --- /dev/null +++ b/lms/djangoapps/course_goals/handlers.py @@ -0,0 +1,25 @@ +""" +Signal handlers for course goals. +""" +from django.db import models +from django.dispatch import receiver + +from course_modes.models import CourseMode +from student.models import CourseEnrollment + +from .api import add_course_goal, remove_course_goal +from .models import GOAL_KEY_CHOICES + + +@receiver(models.signals.post_save, sender=CourseEnrollment, dispatch_uid="update_course_goal_on_enroll_change") +def update_course_goal_on_enroll_change(sender, instance, **kwargs): # pylint: disable=unused-argument + """ + Updates goals as follows on enrollment changes: + 1) Set the course goal to 'certify' when the user enrolls as a verified user. + 2) Remove the course goal when the user's enrollment is no longer active. + """ + course_id = str(instance.course_id).decode('utf8', 'ignore') + if not instance.is_active: + remove_course_goal(instance.user, course_id) + elif instance.mode == CourseMode.VERIFIED: + add_course_goal(instance.user, course_id, GOAL_KEY_CHOICES.certify) diff --git a/lms/djangoapps/course_goals/migrations/0001_initial.py b/lms/djangoapps/course_goals/migrations/0001_initial.py index f976442a39..aeb7f1a62c 100644 --- a/lms/djangoapps/course_goals/migrations/0001_initial.py +++ b/lms/djangoapps/course_goals/migrations/0001_initial.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +from __future__ import absolute_import from django.db import migrations, models from django.conf import settings from opaque_keys.edx.django.models import CourseKeyField diff --git a/lms/djangoapps/course_goals/migrations/0002_auto_20171010_1129.py b/lms/djangoapps/course_goals/migrations/0002_auto_20171010_1129.py index 9be9d86e67..c29d18cae7 100644 --- a/lms/djangoapps/course_goals/migrations/0002_auto_20171010_1129.py +++ b/lms/djangoapps/course_goals/migrations/0002_auto_20171010_1129.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +from __future__ import absolute_import from django.db import migrations, models diff --git a/lms/djangoapps/course_goals/models.py b/lms/djangoapps/course_goals/models.py index 7111da58a7..34866705bb 100644 --- a/lms/djangoapps/course_goals/models.py +++ b/lms/djangoapps/course_goals/models.py @@ -1,17 +1,13 @@ """ Course Goals Models """ +from __future__ import absolute_import + from django.contrib.auth.models import User from django.db import models -from django.dispatch import receiver from django.utils.translation import ugettext_lazy as _ -from opaque_keys.edx.django.models import CourseKeyField from model_utils import Choices - -from .api import add_course_goal, remove_course_goal -from course_modes.models import CourseMode -from student.models import CourseEnrollment - +from opaque_keys.edx.django.models import CourseKeyField # Each goal is represented by a goal key and a string description. GOAL_KEY_CHOICES = Choices( @@ -28,6 +24,10 @@ class CourseGoal(models.Model): .. no_pii: """ + class Meta(object): + app_label = "course_goals" + unique_together = ("user", "course_key") + user = models.ForeignKey(User, blank=False, on_delete=models.CASCADE) course_key = CourseKeyField(max_length=255, db_index=True) goal_key = models.CharField(max_length=100, choices=GOAL_KEY_CHOICES, default=GOAL_KEY_CHOICES.unsure) @@ -38,20 +38,3 @@ class CourseGoal(models.Model): goal=self.goal_key, course=self.course_key, ) - - class Meta: - unique_together = ("user", "course_key") - - -@receiver(models.signals.post_save, sender=CourseEnrollment, dispatch_uid="update_course_goal_on_enroll_change") -def update_course_goal_on_enroll_change(sender, instance, **kwargs): # pylint: disable=unused-argument - """ - Updates goals as follows on enrollment changes: - 1) Set the course goal to 'certify' when the user enrolls as a verified user. - 2) Remove the course goal when the user's enrollment is no longer active. - """ - course_id = str(instance.course_id).decode('utf8', 'ignore') - if not instance.is_active: - remove_course_goal(instance.user, course_id) - elif instance.mode == CourseMode.VERIFIED: - add_course_goal(instance.user, course_id, GOAL_KEY_CHOICES.certify) diff --git a/lms/djangoapps/course_goals/tests/test_api.py b/lms/djangoapps/course_goals/tests/test_api.py index 6966ee7248..0fee1a9959 100644 --- a/lms/djangoapps/course_goals/tests/test_api.py +++ b/lms/djangoapps/course_goals/tests/test_api.py @@ -1,13 +1,15 @@ """ Unit tests for course_goals.api methods. """ -import mock +from __future__ import absolute_import +import mock from django.contrib.auth.models import User -from django.urls import reverse from django.test.utils import override_settings -from lms.djangoapps.course_goals.models import CourseGoal +from django.urls import reverse from rest_framework.test import APIClient + +from lms.djangoapps.course_goals.models import CourseGoal from student.models import CourseEnrollment from track.tests import EventTrackingTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase diff --git a/lms/djangoapps/course_goals/urls.py b/lms/djangoapps/course_goals/urls.py index a914d10915..db0bcb6eec 100644 --- a/lms/djangoapps/course_goals/urls.py +++ b/lms/djangoapps/course_goals/urls.py @@ -1,6 +1,8 @@ """ Course Goals URLs """ +from __future__ import absolute_import + from django.conf.urls import include, url from rest_framework import routers diff --git a/lms/djangoapps/course_goals/views.py b/lms/djangoapps/course_goals/views.py index b50f31f952..541394d1f5 100644 --- a/lms/djangoapps/course_goals/views.py +++ b/lms/djangoapps/course_goals/views.py @@ -3,24 +3,23 @@ Course Goals Views - includes REST API """ from __future__ import absolute_import -from django.contrib.auth import get_user_model from django.conf import settings +from django.contrib.auth import get_user_model from django.db.models.signals import post_save from django.dispatch import receiver from django.http import JsonResponse from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication from eventtracking import tracker from opaque_keys.edx.keys import CourseKey -from openedx.core.lib.api.permissions import IsStaffOrOwner -from rest_framework import permissions, serializers, viewsets, status +from rest_framework import permissions, serializers, status, viewsets from rest_framework.authentication import SessionAuthentication from rest_framework.response import Response +from openedx.core.lib.api.permissions import IsStaffOrOwner from track import segment from .api import get_course_goal_options -from .models import CourseGoal, GOAL_KEY_CHOICES - +from .models import GOAL_KEY_CHOICES, CourseGoal User = get_user_model() diff --git a/lms/envs/common.py b/lms/envs/common.py index a0ac3829e3..0f422f11ed 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -2269,7 +2269,7 @@ INSTALLED_APPS = [ 'openedx.core.djangoapps.waffle_utils', # Course Goals - 'lms.djangoapps.course_goals', + 'lms.djangoapps.course_goals.apps.CourseGoalsConfig', # Features 'openedx.features.course_bookmarks',