feat: allow unsubcribing from a course goal with just a token
* Add unsubscribe_token uuid field to CourseGoal model * Add endpoint to unsubcribe from just a token (no login needed) * Add admin page for the course_goals djangoapp * Add get_course_overview_or_404 utility method * Clean up URL handling in course_home_api AA-907
This commit is contained in:
@@ -3,6 +3,8 @@ CourseOverview api
|
||||
"""
|
||||
import logging
|
||||
|
||||
from django.http.response import Http404
|
||||
|
||||
from openedx.core.djangoapps.catalog.api import get_course_run_details
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.core.djangoapps.content.course_overviews.serializers import (
|
||||
@@ -25,6 +27,18 @@ def get_course_overview_or_none(course_id):
|
||||
return None
|
||||
|
||||
|
||||
def get_course_overview_or_404(course_id):
|
||||
"""
|
||||
Retrieve and return course overview data for the provided course id.
|
||||
|
||||
If the course overview does not exist, raises Http404.
|
||||
"""
|
||||
try:
|
||||
return CourseOverview.get_from_id(course_id)
|
||||
except CourseOverview.DoesNotExist as e:
|
||||
raise Http404(f"Course overview does not exist for {course_id}") from e
|
||||
|
||||
|
||||
def get_pseudo_course_overview(course_id):
|
||||
"""
|
||||
Returns a pseudo course overview object for a deleted course.
|
||||
|
||||
@@ -3,11 +3,13 @@ course_overview api tests
|
||||
"""
|
||||
from mock import patch
|
||||
|
||||
from django.http.response import Http404
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
from openedx.core.djangoapps.catalog.tests.factories import CourseRunFactory
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.core.djangoapps.content.course_overviews.api import (
|
||||
get_course_overview_or_404,
|
||||
get_course_overview_or_none,
|
||||
get_course_overviews,
|
||||
get_course_overviews_from_ids,
|
||||
@@ -27,7 +29,7 @@ class TestCourseOverviewsApi(ModuleStoreTestCase):
|
||||
for _ in range(3):
|
||||
CourseOverviewFactory.create()
|
||||
|
||||
def test_get_course_overview_or_none(self):
|
||||
def test_get_course_overview_or_none_success(self):
|
||||
"""
|
||||
Test for `test_get_course_overview_or_none` function when the overview exists.
|
||||
"""
|
||||
@@ -43,6 +45,22 @@ class TestCourseOverviewsApi(ModuleStoreTestCase):
|
||||
retrieved_course_overview = get_course_overview_or_none(course_run_key)
|
||||
assert retrieved_course_overview is None
|
||||
|
||||
def test_get_course_overview_or_404_success(self):
|
||||
"""
|
||||
Test for `test_get_course_overview_or_404` function when the overview exists.
|
||||
"""
|
||||
course_overview = CourseOverviewFactory.create()
|
||||
retrieved_course_overview = get_course_overview_or_404(course_overview.id)
|
||||
assert course_overview.id == retrieved_course_overview.id
|
||||
|
||||
def test_get_course_overview_or_404_missing(self):
|
||||
"""
|
||||
Test for `test_get_course_overview_or_404` function when the overview does not exist.
|
||||
"""
|
||||
course_run_key = CourseKey.from_string('course-v1:coping+with+deletions')
|
||||
with self.assertRaises(Http404):
|
||||
get_course_overview_or_404(course_run_key)
|
||||
|
||||
def test_get_course_overview_from_ids(self):
|
||||
"""
|
||||
Test for `get_course_overviews_from_ids` function.
|
||||
|
||||
@@ -4,7 +4,7 @@ Course API Serializers. Representing course catalog data
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from lms.djangoapps.course_home_api.progress.v1.serializers import CertificateDataSerializer
|
||||
from lms.djangoapps.course_home_api.progress.serializers import CertificateDataSerializer
|
||||
from openedx.core.lib.api.fields import AbsoluteURLField
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user