Skip to content
This repository has been archived by the owner on Feb 27, 2024. It is now read-only.

Commit

Permalink
Merge pull request #6 from edx-solutions/aamishbaloch/YONK-852
Browse files Browse the repository at this point in the history
YONK-852: Course Settings added to provide support to set language
  • Loading branch information
aamishbaloch committed Jan 8, 2018
2 parents 54ca1d9 + 62f1d8e commit 7152bec
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 2 deletions.
34 changes: 34 additions & 0 deletions course_metadata/migrations/0002_auto_20180105_0836.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
import django.utils.timezone
import openedx.core.djangoapps.xmodule_django.models
import model_utils.fields


class Migration(migrations.Migration):

dependencies = [
('course_metadata', '0001_initial'),
]

operations = [
migrations.CreateModel(
name='CourseSetting',
fields=[
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)),
('id', openedx.core.djangoapps.xmodule_django.models.CourseKeyField(max_length=255, serialize=False, primary_key=True)),
('languages', models.TextField(help_text=b'A comma-separated list of language codes to release to the public.', blank=True)),
],
options={
'abstract': False,
},
),
migrations.AlterField(
model_name='courseaggregatedmetadata',
name='id',
field=openedx.core.djangoapps.xmodule_django.models.CourseKeyField(max_length=255, serialize=False, primary_key=True),
),
]
19 changes: 18 additions & 1 deletion course_metadata/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Models for course_metadata app
"""
import ast
from django.db import models

from model_utils.models import TimeStampedModel
Expand All @@ -16,7 +17,7 @@ class CourseAggregatedMetaData(TimeStampedModel):
This model contains aggregated metadata about a course such as
total modules, total assessments.
"""
id = CourseKeyField(db_index=True, primary_key=True, max_length=255) # pylint: disable=invalid-name
id = CourseKeyField(primary_key=True, max_length=255) # pylint: disable=invalid-name
total_modules = models.IntegerField(default=0)
total_assessments = models.IntegerField(default=0)

Expand All @@ -42,3 +43,19 @@ def get_from_id(course_id):
course_metadata.total_assessments = len(get_course_leaf_nodes(course_id))
course_metadata.save()
return course_metadata


class CourseSetting(TimeStampedModel):
"""
This model have custom course settings.
"""
id = CourseKeyField(primary_key=True, max_length=255)
languages = models.TextField(
blank=True,
help_text="A comma-separated list of language codes to release to the public."
)

@property
def languages_list(self):
data = ast.literal_eval(self.languages)
return data
25 changes: 25 additions & 0 deletions course_metadata/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import ast

from rest_framework import serializers
from openedx.core.lib.api.serializers import CourseKeyField
from course_metadata.models import CourseSetting


class StringListField(serializers.ListField):
child = serializers.CharField(max_length=255)

def to_representation(self, data):
"""
List of object instances -> List of dicts of primitive datatypes.
"""
if isinstance(data, basestring):
data = ast.literal_eval(data)
return data


class CourseSettingSerializer(serializers.ModelSerializer):
id = CourseKeyField(required=False)
languages = StringListField()

class Meta:
model = CourseSetting
47 changes: 47 additions & 0 deletions course_metadata/tests/tests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""
Tests for course_metadata app
"""
from django.core.urlresolvers import reverse
from edx_solutions_api_integration.test_utils import APIClientMixin
from mock_django import mock_signal_receiver

from xmodule.modulestore.django import SignalHandler
Expand Down Expand Up @@ -77,3 +79,48 @@ def test_get_course_aggregate_metadata_by_course_key(self):
"""
course_metadata = CourseAggregatedMetaData.get_from_id(self.course.id)
self.assertEqual(course_metadata.total_assessments, 1)


class CourseSettingTests(ModuleStoreTestCase, APIClientMixin):
""" Test suite for Course Setting """

MODULESTORE = TEST_DATA_SPLIT_MODULESTORE

def setUp(self):
super(CourseSettingTests, self).setUp()

self.course = CourseFactory.create()
self.course_settings_uri = reverse('additional-course-settings', kwargs={'course_id': unicode(self.course.id)})
self.languages = ["it", "de-at", "es", "pt-br"]

def test_course_settings_languages(self):
"""
Test for setting/getting course languages from course settings
"""
data = {"languages": self.languages}
response = self.do_put(self.course_settings_uri, data)
self.assertEqual(response.status_code, 200)

response = self.do_get(self.course_settings_uri)
self.assertEqual(response.status_code, 200)
for language in response.data['languages']:
self.assertIn(language, self.languages)

def test_course_settings_update_languages(self):
"""
Test for updating course languages in course settings
"""
data = {"languages": self.languages}
response = self.do_put(self.course_settings_uri, data)

self.assertEqual(response.status_code, 200)
for language in response.data['languages']:
self.assertIn(language, self.languages)

updated_languages = ["it", "de-at", "es"]
data = {"languages": updated_languages}
response = self.do_put(self.course_settings_uri, data)

self.assertEqual(response.status_code, 200)
for language in response.data['languages']:
self.assertIn(language, self.languages)
15 changes: 15 additions & 0 deletions course_metadata/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from django.conf import settings
from django.conf.urls import patterns, url

from . import views

COURSE_ID_PATTERN = settings.COURSE_ID_PATTERN

urlpatterns = patterns(
'',
url(
r'^{}/settings$'.format(COURSE_ID_PATTERN),
views.CourseSettingView.as_view(),
name='additional-course-settings',
),
)
36 changes: 36 additions & 0 deletions course_metadata/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from opaque_keys.edx.keys import CourseKey
from edx_solutions_api_integration.permissions import SecureRetrieveUpdateAPIView
from course_metadata.models import CourseSetting
from course_metadata.serializers import CourseSettingSerializer


class CourseSettingView(SecureRetrieveUpdateAPIView):
"""
**Use Case**
Create course settings
**Example Requests**
POST /api/server/courses_metadata/{course_id}/settings
**Request Params**
**POST**
-id: course id
-langauges: A comma-separated list of language codes. Example: ['it', 'de-at', 'es', 'pt-br']
**Response Values**
**POST**
If the request is successful, the request returns an HTTP 200 "OK" response.
"""
serializer_class = CourseSettingSerializer
queryset = CourseSetting.objects.all()

def get_object(self):
course_id = CourseKey.from_string(self.kwargs['course_id'])
setting, __ = CourseSetting.objects.get_or_create(id=course_id)
return setting
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

setup(
name='course-edx-platform-extensions',
version='1.0.2',
version='1.0.3',
description='Course metadata management extension for edX platform',
long_description=open('README.rst').read(),
author='edX',
Expand Down

0 comments on commit 7152bec

Please sign in to comment.