Add ConfigurationModel governing integration with the catalog service.
This is the first in a series of commits that will retrieve and use data from the catalog API. Part of ECOM-4566.
This commit is contained in:
@@ -898,6 +898,9 @@ INSTALLED_APPS = (
|
||||
# programs support
|
||||
'openedx.core.djangoapps.programs',
|
||||
|
||||
# Catalog integration
|
||||
'openedx.core.djangoapps.catalog',
|
||||
|
||||
# Self-paced course configuration
|
||||
'openedx.core.djangoapps.self_paced',
|
||||
|
||||
|
||||
@@ -2039,6 +2039,9 @@ INSTALLED_APPS = (
|
||||
# programs support
|
||||
'openedx.core.djangoapps.programs',
|
||||
|
||||
# Catalog integration
|
||||
'openedx.core.djangoapps.catalog',
|
||||
|
||||
# Self-paced course configuration
|
||||
'openedx.core.djangoapps.self_paced',
|
||||
|
||||
|
||||
0
openedx/core/djangoapps/catalog/__init__.py
Normal file
0
openedx/core/djangoapps/catalog/__init__.py
Normal file
31
openedx/core/djangoapps/catalog/migrations/0001_initial.py
Normal file
31
openedx/core/djangoapps/catalog/migrations/0001_initial.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CatalogIntegration',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
|
||||
('internal_api_url', models.URLField(help_text='API root to be used for server-to-server requests (e.g., https://catalog-internal.example.com/api/v1/).', verbose_name='Internal API URL')),
|
||||
('cache_ttl', models.PositiveIntegerField(default=0, help_text='Specified in seconds. Enable caching of API responses by setting this to a value greater than 0.', verbose_name='Cache Time To Live')),
|
||||
('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')),
|
||||
],
|
||||
options={
|
||||
'ordering': ('-change_date',),
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
34
openedx/core/djangoapps/catalog/models.py
Normal file
34
openedx/core/djangoapps/catalog/models.py
Normal file
@@ -0,0 +1,34 @@
|
||||
"""Models governing integration with the catalog service."""
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.db import models
|
||||
|
||||
from config_models.models import ConfigurationModel
|
||||
|
||||
|
||||
class CatalogIntegration(ConfigurationModel):
|
||||
"""Manages configuration for connecting to the catalog service and using its API."""
|
||||
API_NAME = 'catalog'
|
||||
CACHE_KEY = 'catalog.api.data'
|
||||
|
||||
internal_api_url = models.URLField(
|
||||
verbose_name=_('Internal API URL'),
|
||||
help_text=_(
|
||||
'API root to be used for server-to-server requests (e.g., https://catalog-internal.example.com/api/v1/).'
|
||||
)
|
||||
)
|
||||
|
||||
cache_ttl = models.PositiveIntegerField(
|
||||
verbose_name=_('Cache Time To Live'),
|
||||
default=0,
|
||||
help_text=_(
|
||||
'Specified in seconds. Enable caching of API responses by setting this to a value greater than 0.'
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def is_cache_enabled(self):
|
||||
"""Whether responses from the catalog API will be cached."""
|
||||
return self.cache_ttl > 0
|
||||
|
||||
def __unicode__(self):
|
||||
return self.internal_api_url
|
||||
0
openedx/core/djangoapps/catalog/tests/__init__.py
Normal file
0
openedx/core/djangoapps/catalog/tests/__init__.py
Normal file
19
openedx/core/djangoapps/catalog/tests/mixins.py
Normal file
19
openedx/core/djangoapps/catalog/tests/mixins.py
Normal file
@@ -0,0 +1,19 @@
|
||||
"""Mixins to help test catalog integration."""
|
||||
from openedx.core.djangoapps.catalog.models import CatalogIntegration
|
||||
|
||||
|
||||
class CatalogIntegrationMixin(object):
|
||||
"""Utility for working with the catalog service during testing."""
|
||||
|
||||
DEFAULTS = {
|
||||
'enabled': True,
|
||||
'internal_api_url': 'https://catalog-internal.example.com/api/v1/',
|
||||
'cache_ttl': 0,
|
||||
}
|
||||
|
||||
def create_catalog_integration(self, **kwargs):
|
||||
"""Creates a new CatalogIntegration with DEFAULTS, updated with any provided overrides."""
|
||||
fields = dict(self.DEFAULTS, **kwargs)
|
||||
CatalogIntegration(**fields).save()
|
||||
|
||||
return CatalogIntegration.current()
|
||||
23
openedx/core/djangoapps/catalog/tests/test_models.py
Normal file
23
openedx/core/djangoapps/catalog/tests/test_models.py
Normal file
@@ -0,0 +1,23 @@
|
||||
"""Catalog model tests."""
|
||||
import ddt
|
||||
from django.test import TestCase
|
||||
import mock
|
||||
|
||||
from openedx.core.djangoapps.catalog.tests import mixins
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
# ConfigurationModels use the cache. Make every cache get a miss.
|
||||
@mock.patch('config_models.models.cache.get', return_value=None)
|
||||
class TestCatalogIntegration(mixins.CatalogIntegrationMixin, TestCase):
|
||||
"""Tests covering the CatalogIntegration model."""
|
||||
|
||||
@ddt.data(
|
||||
(0, False),
|
||||
(1, True),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_cache_control(self, cache_ttl, is_cache_enabled, _mock_cache):
|
||||
"""Test the behavior of the property controlling whether API responses are cached."""
|
||||
catalog_integration = self.create_catalog_integration(cache_ttl=cache_ttl)
|
||||
self.assertEqual(catalog_integration.is_cache_enabled, is_cache_enabled)
|
||||
Reference in New Issue
Block a user