Merge remote-tracking branch 'origin/release' into dj18-release-merge
Conflicts: common/djangoapps/util/testing.py lms/djangoapps/instructor/views/api.py lms/djangoapps/teams/tests/test_views.py openedx/core/djangoapps/programs/models.py openedx/core/djangoapps/user_api/accounts/tests/test_views.py requirements/edx/github.txt
This commit is contained in:
@@ -1,2 +0,0 @@
|
||||
""" module init will register signal handlers """
|
||||
import contentstore.signals
|
||||
|
||||
@@ -15,7 +15,7 @@ config.readfp(config_file)
|
||||
|
||||
def doc_url(request=None): # pylint: disable=unused-argument
|
||||
"""
|
||||
This function is added in the list of TEMPLATE_CONTEXT_PROCESSORS, which is a django setting for
|
||||
This function is added in the list of TEMPLATES 'context_processors' OPTION, which is a django setting for
|
||||
a tuple of callables that take a request object as their argument and return a dictionary of items
|
||||
to be merged into the RequestContext.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import re
|
||||
from six import add_metaclass
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy, ugettext as _
|
||||
from django.core.urlresolvers import resolve
|
||||
|
||||
from contentstore.utils import course_image_url
|
||||
@@ -350,7 +350,7 @@ class CoursewareSearchIndexer(SearchIndexerBase):
|
||||
'category': 'courseware_index'
|
||||
}
|
||||
|
||||
UNNAMED_MODULE_NAME = _("(Unnamed)")
|
||||
UNNAMED_MODULE_NAME = ugettext_lazy("(Unnamed)")
|
||||
|
||||
@classmethod
|
||||
def normalize_structure_key(cls, structure_key):
|
||||
@@ -417,7 +417,7 @@ class CoursewareSearchIndexer(SearchIndexerBase):
|
||||
while parent is not None:
|
||||
path_component_name = parent.display_name
|
||||
if not path_component_name:
|
||||
path_component_name = cls.UNNAMED_MODULE_NAME
|
||||
path_component_name = unicode(cls.UNNAMED_MODULE_NAME)
|
||||
location_path.append(path_component_name)
|
||||
parent = parent.get_parent()
|
||||
location_path.reverse()
|
||||
|
||||
@@ -14,18 +14,19 @@ class Command(BaseCommand):
|
||||
|commit|: optional argument. If not provided, will not run task.
|
||||
'''
|
||||
|
||||
def handle(self, *args, **options):
|
||||
if len(args) not in {1, 2}:
|
||||
raise CommandError("delete_orphans requires one or more arguments: <course_id> |commit|")
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('course_id')
|
||||
parser.add_argument('--commit', action='store')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
try:
|
||||
course_key = CourseKey.from_string(args[0])
|
||||
course_key = CourseKey.from_string(options['course_id'])
|
||||
except InvalidKeyError:
|
||||
raise CommandError("Invalid course key.")
|
||||
|
||||
commit = False
|
||||
if len(args) == 2:
|
||||
commit = args[1] == 'commit'
|
||||
if options['commit']:
|
||||
commit = options['commit'] == 'commit'
|
||||
|
||||
if commit:
|
||||
print 'Deleting orphans from the course:'
|
||||
|
||||
@@ -18,23 +18,24 @@ class Command(BaseCommand):
|
||||
"""
|
||||
help = 'Export the specified data directory into the default ModuleStore'
|
||||
|
||||
def handle(self, *args, **options):
|
||||
"Execute the command"
|
||||
if len(args) != 2:
|
||||
raise CommandError("export requires two arguments: <course id> <output path>")
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('course_id')
|
||||
parser.add_argument('output_path')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
"""Execute the command"""
|
||||
try:
|
||||
course_key = CourseKey.from_string(args[0])
|
||||
course_key = CourseKey.from_string(options['course_id'])
|
||||
except InvalidKeyError:
|
||||
try:
|
||||
course_key = SlashSeparatedCourseKey.from_deprecated_string(args[0])
|
||||
course_key = SlashSeparatedCourseKey.from_deprecated_string(options['course_id'])
|
||||
except InvalidKeyError:
|
||||
raise CommandError("Invalid course_key: '%s'. " % args[0])
|
||||
raise CommandError("Invalid course_key: '%s'." % options['course_id'])
|
||||
|
||||
if not modulestore().get_course(course_key):
|
||||
raise CommandError("Course with %s key not found." % args[0])
|
||||
raise CommandError("Course with %s key not found." % options['course_id'])
|
||||
|
||||
output_path = args[1]
|
||||
output_path = options['output_path']
|
||||
|
||||
print "Exporting course id = {0} to {1}".format(course_key, output_path)
|
||||
|
||||
|
||||
@@ -13,12 +13,14 @@ class Command(BaseCommand):
|
||||
"""Fix a course's item not found errors"""
|
||||
help = "Fix a course's ItemNotFound errors"
|
||||
|
||||
def handle(self, *args, **options):
|
||||
"Execute the command"
|
||||
if len(args) != 1:
|
||||
raise CommandError("requires 1 argument: <course_id>")
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('course_id')
|
||||
|
||||
course_key = CourseKey.from_string(args[0])
|
||||
def handle(self, *args, **options):
|
||||
"""Execute the command"""
|
||||
course_id = options.get('course_id', None)
|
||||
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
# for now only support on split mongo
|
||||
# pylint: disable=protected-access
|
||||
owning_store = modulestore()._get_modulestore_for_courselike(course_key)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
"""
|
||||
Script for importing courseware from XML format
|
||||
"""
|
||||
from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError, make_option
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django_comment_common.utils import (seed_permissions_roles,
|
||||
are_permissions_roles_seeded)
|
||||
from xmodule.modulestore.xml_importer import import_course_from_xml
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Tests running the delete_orphan command"""
|
||||
|
||||
import ddt
|
||||
from django.core.management import call_command
|
||||
from django.core.management import call_command, CommandError
|
||||
from contentstore.tests.test_orphan import TestOrphanBase
|
||||
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
@@ -14,6 +14,13 @@ class TestDeleteOrphan(TestOrphanBase):
|
||||
Tests for running the delete_orphan management command.
|
||||
Inherits from TestOrphan in order to use its setUp method.
|
||||
"""
|
||||
def test_no_args(self):
|
||||
"""
|
||||
Test delete_orphans command with no arguments
|
||||
"""
|
||||
with self.assertRaisesRegexp(CommandError, 'Error: too few arguments'):
|
||||
call_command('delete_orphans')
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo)
|
||||
def test_delete_orphans_no_commit(self, default_store):
|
||||
"""
|
||||
@@ -35,7 +42,7 @@ class TestDeleteOrphan(TestOrphanBase):
|
||||
"""
|
||||
course = self.create_course_with_orphans(default_store)
|
||||
|
||||
call_command('delete_orphans', unicode(course.id), 'commit')
|
||||
call_command('delete_orphans', unicode(course.id), commit='commit')
|
||||
|
||||
# make sure this module wasn't deleted
|
||||
self.assertTrue(self.store.has_item(course.id.make_usage_key('html', 'multi_parent_html')))
|
||||
@@ -59,7 +66,7 @@ class TestDeleteOrphan(TestOrphanBase):
|
||||
|
||||
# call delete orphans, specifying the published branch
|
||||
# of the course
|
||||
call_command('delete_orphans', unicode(published_branch), 'commit')
|
||||
call_command('delete_orphans', unicode(published_branch), commit='commit')
|
||||
|
||||
# now all orphans should be deleted
|
||||
self.assertOrphanCount(course.id, 0)
|
||||
|
||||
@@ -24,11 +24,9 @@ class TestArgParsingCourseExport(unittest.TestCase):
|
||||
"""
|
||||
Test export command with no arguments
|
||||
"""
|
||||
errstring = "export requires two arguments: <course id> <output path>"
|
||||
with self.assertRaises(SystemExit) as ex:
|
||||
with self.assertRaisesRegexp(CommandError, errstring):
|
||||
call_command('export')
|
||||
self.assertEqual(ex.exception.code, 1)
|
||||
errstring = "Error: too few arguments"
|
||||
with self.assertRaisesRegexp(CommandError, errstring):
|
||||
call_command('export')
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -59,11 +57,9 @@ class TestCourseExport(ModuleStoreTestCase):
|
||||
"Could not find course in {}".format(store)
|
||||
)
|
||||
# Test `export` management command with invalid course_id
|
||||
errstring = "Invalid course_key 'InvalidCourseID'."
|
||||
with self.assertRaises(SystemExit) as ex:
|
||||
with self.assertRaisesRegexp(CommandError, errstring):
|
||||
call_command('export', "InvalidCourseID", self.temp_dir_1)
|
||||
self.assertEqual(ex.exception.code, 1)
|
||||
errstring = "Invalid course_key: 'InvalidCourseID'."
|
||||
with self.assertRaisesRegexp(CommandError, errstring):
|
||||
call_command('export', "InvalidCourseID", self.temp_dir_1)
|
||||
|
||||
# Test `export` management command with correct course_id
|
||||
for output_dir in [self.temp_dir_1, self.temp_dir_2]:
|
||||
@@ -74,7 +70,5 @@ class TestCourseExport(ModuleStoreTestCase):
|
||||
Test export command with a valid course key that doesn't exist
|
||||
"""
|
||||
errstring = "Course with x/y/z key not found."
|
||||
with self.assertRaises(SystemExit) as ex:
|
||||
with self.assertRaisesRegexp(CommandError, errstring):
|
||||
call_command('export', "x/y/z", self.temp_dir_1)
|
||||
self.assertEqual(ex.exception.code, 1)
|
||||
with self.assertRaisesRegexp(CommandError, errstring):
|
||||
call_command('export', "x/y/z", self.temp_dir_1)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Tests for the fix_not_found management command
|
||||
"""
|
||||
|
||||
from django.core.management import call_command
|
||||
from django.core.management import CommandError, call_command
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
@@ -12,12 +12,19 @@ class TestFixNotFound(ModuleStoreTestCase):
|
||||
"""
|
||||
Tests for the fix_not_found management command
|
||||
"""
|
||||
def test_no_args(self):
|
||||
"""
|
||||
Test fix_not_found command with no arguments
|
||||
"""
|
||||
with self.assertRaisesRegexp(CommandError, "Error: too few arguments"):
|
||||
call_command('fix_not_found')
|
||||
|
||||
def test_fix_not_found_non_split(self):
|
||||
"""
|
||||
The management command doesn't work on non split courses
|
||||
"""
|
||||
course = CourseFactory.create(default_store=ModuleStoreEnum.Type.mongo)
|
||||
with self.assertRaises(SystemExit):
|
||||
with self.assertRaisesRegexp(CommandError, "The owning modulestore does not support this command."):
|
||||
call_command("fix_not_found", unicode(course.id))
|
||||
|
||||
def test_fix_not_found(self):
|
||||
|
||||
@@ -56,57 +56,33 @@ class TestGitExport(CourseTestCase):
|
||||
Test that the command interface works. Ignore stderr for clean
|
||||
test output.
|
||||
"""
|
||||
with self.assertRaises(SystemExit) as ex:
|
||||
with self.assertRaisesRegexp(CommandError, 'This script requires.*'):
|
||||
call_command('git_export', 'blah', 'blah', 'blah',
|
||||
stderr=StringIO.StringIO())
|
||||
self.assertEqual(ex.exception.code, 1)
|
||||
with self.assertRaisesRegexp(CommandError, 'This script requires.*'):
|
||||
call_command('git_export', 'blah', 'blah', 'blah', stderr=StringIO.StringIO())
|
||||
|
||||
with self.assertRaises(SystemExit) as ex:
|
||||
with self.assertRaisesRegexp(CommandError, 'This script requires.*'):
|
||||
call_command('git_export', stderr=StringIO.StringIO())
|
||||
self.assertEqual(ex.exception.code, 1)
|
||||
with self.assertRaisesRegexp(CommandError, 'This script requires.*'):
|
||||
call_command('git_export', stderr=StringIO.StringIO())
|
||||
|
||||
# Send bad url to get course not exported
|
||||
with self.assertRaises(SystemExit) as ex:
|
||||
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.URL_BAD)):
|
||||
call_command('git_export', 'foo/bar/baz', 'silly',
|
||||
stderr=StringIO.StringIO())
|
||||
self.assertEqual(ex.exception.code, 1)
|
||||
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.URL_BAD)):
|
||||
call_command('git_export', 'foo/bar/baz', 'silly', stderr=StringIO.StringIO())
|
||||
|
||||
# Send bad course_id to get course not exported
|
||||
with self.assertRaises(SystemExit) as ex:
|
||||
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.BAD_COURSE)):
|
||||
call_command('git_export', 'foo/bar:baz', 'silly',
|
||||
stderr=StringIO.StringIO())
|
||||
self.assertEqual(ex.exception.code, 1)
|
||||
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.BAD_COURSE)):
|
||||
call_command('git_export', 'foo/bar:baz', 'silly', stderr=StringIO.StringIO())
|
||||
|
||||
def test_error_output(self):
|
||||
"""
|
||||
Verify that error output is actually resolved as the correct string
|
||||
"""
|
||||
output = StringIO.StringIO()
|
||||
with self.assertRaises(SystemExit):
|
||||
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.BAD_COURSE)):
|
||||
call_command(
|
||||
'git_export', 'foo/bar:baz', 'silly',
|
||||
stdout=output, stderr=output
|
||||
)
|
||||
self.assertIn('Bad course location provided', output.getvalue())
|
||||
output.close()
|
||||
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.BAD_COURSE)):
|
||||
call_command(
|
||||
'git_export', 'foo/bar:baz', 'silly'
|
||||
)
|
||||
|
||||
output = StringIO.StringIO()
|
||||
with self.assertRaises(SystemExit):
|
||||
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.URL_BAD)):
|
||||
call_command(
|
||||
'git_export', 'foo/bar/baz', 'silly',
|
||||
stdout=output, stderr=output
|
||||
)
|
||||
self.assertIn(
|
||||
'Non writable git url provided. Expecting something like:'
|
||||
' git@github.com:mitocw/edx4edx_lite.git',
|
||||
output.getvalue()
|
||||
)
|
||||
output.close()
|
||||
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.URL_BAD)):
|
||||
call_command(
|
||||
'git_export', 'foo/bar/baz', 'silly'
|
||||
)
|
||||
|
||||
def test_bad_git_url(self):
|
||||
"""
|
||||
|
||||
@@ -6,7 +6,6 @@ import mock
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from common.test.utils import nostderr
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, LibraryFactory
|
||||
|
||||
from contentstore.management.commands.reindex_course import Command as ReindexCommand
|
||||
@@ -48,36 +47,30 @@ class TestReindexCourse(ModuleStoreTestCase):
|
||||
|
||||
def test_given_no_arguments_raises_command_error(self):
|
||||
""" Test that raises CommandError for incorrect arguments """
|
||||
with self.assertRaises(SystemExit), nostderr():
|
||||
with self.assertRaisesRegexp(CommandError, ".* requires one or more arguments .*"):
|
||||
call_command('reindex_course')
|
||||
with self.assertRaisesRegexp(CommandError, ".* requires one or more arguments.*"):
|
||||
call_command('reindex_course')
|
||||
|
||||
@ddt.data('qwerty', 'invalid_key', 'xblock-v1:qwe+rty')
|
||||
@ddt.data('qwerty', 'invalid_key', 'xblockv1:qwerty')
|
||||
def test_given_invalid_course_key_raises_not_found(self, invalid_key):
|
||||
""" Test that raises InvalidKeyError for invalid keys """
|
||||
errstring = "Invalid course_key: '%s'." % invalid_key
|
||||
with self.assertRaises(SystemExit) as ex:
|
||||
with self.assertRaisesRegexp(CommandError, errstring):
|
||||
call_command('reindex_course', invalid_key)
|
||||
self.assertEqual(ex.exception.code, 1)
|
||||
err_string = "Invalid course_key: '{0}'".format(invalid_key)
|
||||
with self.assertRaisesRegexp(CommandError, err_string):
|
||||
call_command('reindex_course', invalid_key)
|
||||
|
||||
def test_given_library_key_raises_command_error(self):
|
||||
""" Test that raises CommandError if library key is passed """
|
||||
with self.assertRaises(SystemExit), nostderr():
|
||||
with self.assertRaisesRegexp(SearchIndexingError, ".* is not a course key"):
|
||||
call_command('reindex_course', unicode(self._get_lib_key(self.first_lib)))
|
||||
with self.assertRaisesRegexp(CommandError, ".* is not a course key"):
|
||||
call_command('reindex_course', unicode(self._get_lib_key(self.first_lib)))
|
||||
|
||||
with self.assertRaises(SystemExit), nostderr():
|
||||
with self.assertRaisesRegexp(SearchIndexingError, ".* is not a course key"):
|
||||
call_command('reindex_course', unicode(self._get_lib_key(self.second_lib)))
|
||||
with self.assertRaisesRegexp(CommandError, ".* is not a course key"):
|
||||
call_command('reindex_course', unicode(self._get_lib_key(self.second_lib)))
|
||||
|
||||
with self.assertRaises(SystemExit), nostderr():
|
||||
with self.assertRaisesRegexp(SearchIndexingError, ".* is not a course key"):
|
||||
call_command(
|
||||
'reindex_course',
|
||||
unicode(self.second_course.id),
|
||||
unicode(self._get_lib_key(self.first_lib))
|
||||
)
|
||||
with self.assertRaisesRegexp(CommandError, ".* is not a course key"):
|
||||
call_command(
|
||||
'reindex_course',
|
||||
unicode(self.second_course.id),
|
||||
unicode(self._get_lib_key(self.first_lib))
|
||||
)
|
||||
|
||||
def test_given_id_list_indexes_courses(self):
|
||||
""" Test that reindexes courses when given single course key or a list of course keys """
|
||||
|
||||
@@ -6,7 +6,6 @@ import mock
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from common.test.utils import nostderr
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, LibraryFactory
|
||||
|
||||
from opaque_keys import InvalidKeyError
|
||||
@@ -50,9 +49,8 @@ class TestReindexLibrary(ModuleStoreTestCase):
|
||||
|
||||
def test_given_no_arguments_raises_command_error(self):
|
||||
""" Test that raises CommandError for incorrect arguments """
|
||||
with self.assertRaises(SystemExit), nostderr():
|
||||
with self.assertRaisesRegexp(CommandError, ".* requires one or more arguments .*"):
|
||||
call_command('reindex_library')
|
||||
with self.assertRaisesRegexp(CommandError, ".* requires one or more arguments.*"):
|
||||
call_command('reindex_library')
|
||||
|
||||
@ddt.data('qwerty', 'invalid_key', 'xblock-v1:qwe+rty')
|
||||
def test_given_invalid_lib_key_raises_not_found(self, invalid_key):
|
||||
@@ -62,21 +60,18 @@ class TestReindexLibrary(ModuleStoreTestCase):
|
||||
|
||||
def test_given_course_key_raises_command_error(self):
|
||||
""" Test that raises CommandError if course key is passed """
|
||||
with self.assertRaises(SystemExit), nostderr():
|
||||
with self.assertRaisesRegexp(CommandError, ".* is not a library key"):
|
||||
call_command('reindex_library', unicode(self.first_course.id))
|
||||
with self.assertRaisesRegexp(CommandError, ".* is not a library key"):
|
||||
call_command('reindex_library', unicode(self.first_course.id))
|
||||
|
||||
with self.assertRaises(SystemExit), nostderr():
|
||||
with self.assertRaisesRegexp(CommandError, ".* is not a library key"):
|
||||
call_command('reindex_library', unicode(self.second_course.id))
|
||||
with self.assertRaisesRegexp(CommandError, ".* is not a library key"):
|
||||
call_command('reindex_library', unicode(self.second_course.id))
|
||||
|
||||
with self.assertRaises(SystemExit), nostderr():
|
||||
with self.assertRaisesRegexp(CommandError, ".* is not a library key"):
|
||||
call_command(
|
||||
'reindex_library',
|
||||
unicode(self.second_course.id),
|
||||
unicode(self._get_lib_key(self.first_lib))
|
||||
)
|
||||
with self.assertRaisesRegexp(CommandError, ".* is not a library key"):
|
||||
call_command(
|
||||
'reindex_library',
|
||||
unicode(self.second_course.id),
|
||||
unicode(self._get_lib_key(self.first_lib))
|
||||
)
|
||||
|
||||
def test_given_id_list_indexes_libraries(self):
|
||||
""" Test that reindexes libraries when given single library key or a list of library keys """
|
||||
|
||||
@@ -1,80 +1,43 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding model 'VideoUploadConfig'
|
||||
db.create_table('contentstore_videouploadconfig', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('change_date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
||||
('changed_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, on_delete=models.PROTECT)),
|
||||
('enabled', self.gf('django.db.models.fields.BooleanField')(default=False)),
|
||||
('profile_whitelist', self.gf('django.db.models.fields.TextField')(blank=True)),
|
||||
('status_whitelist', self.gf('django.db.models.fields.TextField')(blank=True)),
|
||||
))
|
||||
db.send_create_signal('contentstore', ['VideoUploadConfig'])
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
if not db.dry_run:
|
||||
orm.VideoUploadConfig.objects.create(
|
||||
profile_whitelist="desktop_mp4,desktop_webm,mobile_low,youtube",
|
||||
status_whitelist="Uploading,In Progress,Complete,Failed,Invalid Token,Unknown"
|
||||
)
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting model 'VideoUploadConfig'
|
||||
db.delete_table('contentstore_videouploadconfig')
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contentstore.videouploadconfig': {
|
||||
'Meta': {'object_name': 'VideoUploadConfig'},
|
||||
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
|
||||
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'profile_whitelist': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'status_whitelist': ('django.db.models.fields.TextField', [], {'blank': 'True'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['contentstore']
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='PushNotificationConfig',
|
||||
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')),
|
||||
('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,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='VideoUploadConfig',
|
||||
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')),
|
||||
('profile_whitelist', models.TextField(help_text=b'A comma-separated list of names of profiles to include in video encoding downloads.', blank=True)),
|
||||
('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,
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Deleting field 'VideoUploadConfig.status_whitelist'
|
||||
db.delete_column('contentstore_videouploadconfig', 'status_whitelist')
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Adding field 'VideoUploadConfig.status_whitelist'
|
||||
db.add_column('contentstore_videouploadconfig', 'status_whitelist',
|
||||
self.gf('django.db.models.fields.TextField')(default='', blank=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contentstore.videouploadconfig': {
|
||||
'Meta': {'object_name': 'VideoUploadConfig'},
|
||||
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
|
||||
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'profile_whitelist': ('django.db.models.fields.TextField', [], {'blank': 'True'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['contentstore']
|
||||
@@ -1,80 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from south.utils import datetime_utils as datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding model 'PushNotificationConfig'
|
||||
db.create_table('contentstore_pushnotificationconfig', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('change_date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
||||
('changed_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, on_delete=models.PROTECT)),
|
||||
('enabled', self.gf('django.db.models.fields.BooleanField')(default=False)),
|
||||
))
|
||||
db.send_create_signal('contentstore', ['PushNotificationConfig'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting model 'PushNotificationConfig'
|
||||
db.delete_table('contentstore_pushnotificationconfig')
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contentstore.pushnotificationconfig': {
|
||||
'Meta': {'object_name': 'PushNotificationConfig'},
|
||||
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
|
||||
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'contentstore.videouploadconfig': {
|
||||
'Meta': {'object_name': 'VideoUploadConfig'},
|
||||
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
|
||||
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'profile_whitelist': ('django.db.models.fields.TextField', [], {'blank': 'True'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['contentstore']
|
||||
2
cms/djangoapps/contentstore/startup.py
Normal file
2
cms/djangoapps/contentstore/startup.py
Normal file
@@ -0,0 +1,2 @@
|
||||
""" will register signal handlers, moved out of __init__.py to ensure correct loading order post Django 1.7 """
|
||||
from . import signals # pylint: disable=unused-import
|
||||
@@ -187,7 +187,7 @@ def _get_entrance_exam(request, course_key): # pylint: disable=W0613
|
||||
exam_descriptor = modulestore().get_item(exam_key)
|
||||
return HttpResponse(
|
||||
escape_json_dumps({'locator': unicode(exam_descriptor.location)}),
|
||||
status=200, mimetype='application/json')
|
||||
status=200, content_type='application/json')
|
||||
except ItemNotFoundError:
|
||||
return HttpResponse(status=404)
|
||||
|
||||
|
||||
@@ -301,7 +301,7 @@ def xblock_view_handler(request, usage_key_string, view_name):
|
||||
|
||||
hashed_resources = OrderedDict()
|
||||
for resource in fragment.resources:
|
||||
hashed_resources[hash_resource(resource)] = resource
|
||||
hashed_resources[hash_resource(resource)] = resource._asdict()
|
||||
|
||||
return JsonResponse({
|
||||
'html': fragment.content,
|
||||
|
||||
@@ -38,7 +38,7 @@ from .session_kv_store import SessionKeyValueStore
|
||||
from .helpers import render_from_lms
|
||||
|
||||
from contentstore.views.access import get_user_role
|
||||
from cms.djangoapps.xblock_config.models import StudioConfig
|
||||
from xblock_config.models import StudioConfig
|
||||
|
||||
__all__ = ['preview_handler']
|
||||
|
||||
|
||||
@@ -610,12 +610,12 @@ class TestCourseReIndex(CourseTestCase):
|
||||
response = non_staff_client.get(index_url, {}, HTTP_ACCEPT='application/json')
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_content_type_none(self):
|
||||
def test_empty_content_type(self):
|
||||
"""
|
||||
Test json content type is set if none is selected
|
||||
Test json content type is set if '' is selected
|
||||
"""
|
||||
index_url = reverse_course_url('course_search_index_handler', self.course.id)
|
||||
response = self.client.get(index_url, {}, CONTENT_TYPE=None)
|
||||
response = self.client.get(index_url, {}, CONTENT_TYPE='')
|
||||
|
||||
# A course with the default release date should display as "Unscheduled"
|
||||
self.assertIn(self.SUCCESSFUL_RESPONSE, response.content)
|
||||
|
||||
@@ -17,7 +17,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from contentstore.views.preview import get_preview_fragment, _preview_module_system
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.test_asides import AsideTestType
|
||||
from cms.djangoapps.xblock_config.models import StudioConfig
|
||||
from xblock_config.models import StudioConfig
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
|
||||
|
||||
@@ -1,74 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding model 'CourseCreator'
|
||||
db.create_table('course_creators_coursecreator', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], unique=True)),
|
||||
('state_changed', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
||||
('state', self.gf('django.db.models.fields.CharField')(default='unrequested', max_length=24)),
|
||||
('note', self.gf('django.db.models.fields.CharField')(max_length=512, blank=True)),
|
||||
))
|
||||
db.send_create_signal('course_creators', ['CourseCreator'])
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting model 'CourseCreator'
|
||||
db.delete_table('course_creators_coursecreator')
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'course_creators.coursecreator': {
|
||||
'Meta': {'object_name': 'CourseCreator'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'note': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
|
||||
'state': ('django.db.models.fields.CharField', [], {'default': "'unrequested'", 'max_length': '24'}),
|
||||
'state_changed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['course_creators']
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CourseCreator',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('state_changed', models.DateTimeField(help_text='The date when state was last updated', verbose_name=b'state last updated', auto_now_add=True)),
|
||||
('state', models.CharField(default=b'unrequested', help_text='Current course creator state', max_length=24, choices=[(b'unrequested', 'unrequested'), (b'pending', 'pending'), (b'granted', 'granted'), (b'denied', 'denied')])),
|
||||
('note', models.CharField(help_text='Optional notes about this user (for example, why course creation access was denied)', max_length=512, blank=True)),
|
||||
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, help_text='Studio user')),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
@@ -36,7 +36,7 @@ class CourseCreator(models.Model):
|
||||
(DENIED, _(u'denied')),
|
||||
)
|
||||
|
||||
user = models.ForeignKey(User, help_text=_("Studio user"), unique=True)
|
||||
user = models.OneToOneField(User, help_text=_("Studio user"))
|
||||
state_changed = models.DateTimeField('state last updated', auto_now_add=True,
|
||||
help_text=_("The date when state was last updated"))
|
||||
state = models.CharField(max_length=24, blank=False, choices=STATES, default=UNREQUESTED,
|
||||
|
||||
@@ -105,7 +105,7 @@ class CourseCreatorAdminTest(TestCase):
|
||||
# message sent. Admin message will follow.
|
||||
base_num_emails = 1 if expect_sent_to_user else 0
|
||||
if expect_sent_to_admin:
|
||||
context = {'user_name': "test_user", 'user_email': 'test_user+courses@edx.org'}
|
||||
context = {'user_name': "test_user", 'user_email': u'test_user+courses@edx.org'}
|
||||
self.assertEquals(base_num_emails + 1, len(mail.outbox), 'Expected admin message to be sent')
|
||||
sent_mail = mail.outbox[base_num_emails]
|
||||
self.assertEquals(
|
||||
@@ -166,10 +166,10 @@ class CourseCreatorAdminTest(TestCase):
|
||||
# try logging in 30 times, the default limit in the number of failed
|
||||
# login attempts in one 5 minute period before the rate gets limited
|
||||
for _ in xrange(30):
|
||||
response = self.client.post('/admin/', post_params)
|
||||
response = self.client.post('/admin/login/', post_params)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
|
||||
response = self.client.post('/admin/', post_params)
|
||||
response = self.client.post('/admin/login/', post_params)
|
||||
# Since we are using the default rate limit behavior, we are
|
||||
# expecting this to return a 403 error to indicate that there have
|
||||
# been too many attempts
|
||||
|
||||
@@ -4,6 +4,6 @@ Django admin dashboard configuration for LMS XBlock infrastructure.
|
||||
|
||||
from django.contrib import admin
|
||||
from config_models.admin import ConfigurationModelAdmin
|
||||
from cms.djangoapps.xblock_config.models import StudioConfig
|
||||
from xblock_config.models import StudioConfig
|
||||
|
||||
admin.site.register(StudioConfig, ConfigurationModelAdmin)
|
||||
|
||||
@@ -1,74 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding model 'StudioConfig'
|
||||
db.create_table('xblock_config_studioconfig', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('change_date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
||||
('changed_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, on_delete=models.PROTECT)),
|
||||
('enabled', self.gf('django.db.models.fields.BooleanField')(default=False)),
|
||||
('disabled_blocks', self.gf('django.db.models.fields.TextField')(default='about course_info static_tab')),
|
||||
))
|
||||
db.send_create_signal('xblock_config', ['StudioConfig'])
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting model 'StudioConfig'
|
||||
db.delete_table('xblock_config_studioconfig')
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'xblock_config.studioconfig': {
|
||||
'Meta': {'object_name': 'StudioConfig'},
|
||||
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
|
||||
'disabled_blocks': ('django.db.models.fields.TextField', [], {'default': "'about course_info static_tab'"}),
|
||||
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['xblock_config']
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='StudioConfig',
|
||||
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')),
|
||||
('disabled_blocks', models.TextField(default=b'about course_info static_tab', help_text=b'Space-separated list of XBlocks on which XBlockAsides should never render in studio')),
|
||||
('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,
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
@@ -79,6 +79,7 @@ DATABASES = {
|
||||
'OPTIONS': {
|
||||
'timeout': 30,
|
||||
},
|
||||
'ATOMIC_REQUESTS': True,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +101,7 @@ USE_I18N = True
|
||||
# Include the lettuce app for acceptance testing, including the 'harvest' django-admin command
|
||||
# django.contrib.staticfiles used to be loaded by lettuce, now we must add it ourselves
|
||||
# django.contrib.staticfiles is not added to lms as there is a ^/static$ route built in to the app
|
||||
INSTALLED_APPS += ('lettuce.django', 'django.contrib.staticfiles')
|
||||
INSTALLED_APPS += ('lettuce.django',)
|
||||
LETTUCE_APPS = ('contentstore',)
|
||||
LETTUCE_BROWSER = os.environ.get('LETTUCE_BROWSER', 'chrome')
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ CONFIG_PREFIX = SERVICE_VARIANT + "." if SERVICE_VARIANT else ""
|
||||
############### ALWAYS THE SAME ################################
|
||||
|
||||
DEBUG = False
|
||||
TEMPLATE_DEBUG = False
|
||||
|
||||
EMAIL_BACKEND = 'django_ses.SESBackend'
|
||||
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
|
||||
@@ -69,11 +68,6 @@ BROKER_HEARTBEAT_CHECKRATE = 2
|
||||
# Each worker should only fetch one message at a time
|
||||
CELERYD_PREFETCH_MULTIPLIER = 1
|
||||
|
||||
# Skip djcelery migrations, since we don't use the database as the broker
|
||||
SOUTH_MIGRATION_MODULES = {
|
||||
'djcelery': 'ignore',
|
||||
}
|
||||
|
||||
# Rename the exchange and queues for each variant
|
||||
|
||||
QUEUE_VARIANT = CONFIG_PREFIX.lower()
|
||||
@@ -130,6 +124,12 @@ LMS_BASE = ENV_TOKENS.get('LMS_BASE')
|
||||
|
||||
SITE_NAME = ENV_TOKENS['SITE_NAME']
|
||||
|
||||
ALLOWED_HOSTS = [
|
||||
# TODO: bbeggs remove this before prod, temp fix to get load testing running
|
||||
"*",
|
||||
ENV_TOKENS.get('CMS_BASE')
|
||||
]
|
||||
|
||||
LOG_DIR = ENV_TOKENS['LOG_DIR']
|
||||
|
||||
CACHES = ENV_TOKENS['CACHES']
|
||||
@@ -249,6 +249,8 @@ EMAIL_HOST_PASSWORD = AUTH_TOKENS.get('EMAIL_HOST_PASSWORD', EMAIL_HOST_PASSWORD
|
||||
# Note that this is the Studio key for Segment. There is a separate key for the LMS.
|
||||
CMS_SEGMENT_KEY = AUTH_TOKENS.get('SEGMENT_KEY')
|
||||
|
||||
SECRET_KEY = AUTH_TOKENS['SECRET_KEY']
|
||||
|
||||
AWS_ACCESS_KEY_ID = AUTH_TOKENS["AWS_ACCESS_KEY_ID"]
|
||||
if AWS_ACCESS_KEY_ID == "":
|
||||
AWS_ACCESS_KEY_ID = None
|
||||
@@ -265,6 +267,11 @@ else:
|
||||
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
|
||||
|
||||
DATABASES = AUTH_TOKENS['DATABASES']
|
||||
|
||||
# Enable automatic transaction management on all databases
|
||||
for database_name in DATABASES:
|
||||
DATABASES[database_name]['ATOMIC_REQUESTS'] = True
|
||||
|
||||
MODULESTORE = convert_module_store_setting_if_needed(AUTH_TOKENS.get('MODULESTORE', MODULESTORE))
|
||||
CONTENTSTORE = AUTH_TOKENS['CONTENTSTORE']
|
||||
DOC_STORE_CONFIG = AUTH_TOKENS['DOC_STORE_CONFIG']
|
||||
|
||||
@@ -59,6 +59,11 @@ from xmodule.modulestore.edit_info import EditInfoMixin
|
||||
from xmodule.mixin import LicenseMixin
|
||||
|
||||
############################ FEATURE CONFIGURATION #############################
|
||||
|
||||
|
||||
# Dummy secret key for dev/test
|
||||
SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd'
|
||||
|
||||
STUDIO_NAME = "Studio"
|
||||
STUDIO_SHORT_NAME = "Studio"
|
||||
FEATURES = {
|
||||
@@ -206,8 +211,9 @@ sys.path.append(COMMON_ROOT / 'djangoapps')
|
||||
GEOIP_PATH = REPO_ROOT / "common/static/data/geoip/GeoIP.dat"
|
||||
GEOIPV6_PATH = REPO_ROOT / "common/static/data/geoip/GeoIPv6.dat"
|
||||
|
||||
############################# WEB CONFIGURATION #############################
|
||||
# This is where we stick our compiled template files.
|
||||
############################# TEMPLATE CONFIGURATION #############################
|
||||
# Mako templating
|
||||
# TODO: Move the Mako templating into a different engine in TEMPLATES below.
|
||||
import tempfile
|
||||
MAKO_MODULE_DIR = os.path.join(tempfile.gettempdir(), 'mako_cms')
|
||||
MAKO_TEMPLATES = {}
|
||||
@@ -222,25 +228,44 @@ MAKO_TEMPLATES['main'] = [
|
||||
for namespace, template_dirs in lms.envs.common.MAKO_TEMPLATES.iteritems():
|
||||
MAKO_TEMPLATES['lms.' + namespace] = template_dirs
|
||||
|
||||
TEMPLATE_DIRS = MAKO_TEMPLATES['main']
|
||||
# Django templating
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
# Don't look for template source files inside installed applications.
|
||||
'APP_DIRS': False,
|
||||
# Instead, look for template source files in these dirs.
|
||||
'DIRS': MAKO_TEMPLATES['main'],
|
||||
# Options specific to this backend.
|
||||
'OPTIONS': {
|
||||
'loaders': (
|
||||
'django.template.loaders.filesystem.Loader',
|
||||
'django.template.loaders.app_directories.Loader',
|
||||
),
|
||||
'context_processors': (
|
||||
'django.template.context_processors.request',
|
||||
'django.template.context_processors.static',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'django.template.context_processors.i18n',
|
||||
'django.contrib.auth.context_processors.auth', # this is required for admin
|
||||
'django.template.context_processors.csrf',
|
||||
'dealer.contrib.django.staff.context_processor', # access git revision
|
||||
'contentstore.context_processors.doc_url',
|
||||
),
|
||||
# Change 'debug' in your environment settings files - not here.
|
||||
'debug': False
|
||||
}
|
||||
}
|
||||
]
|
||||
DEFAULT_TEMPLATE_ENGINE = TEMPLATES[0]
|
||||
|
||||
##############################################################################
|
||||
|
||||
EDX_ROOT_URL = ''
|
||||
|
||||
LOGIN_REDIRECT_URL = EDX_ROOT_URL + '/signin'
|
||||
LOGIN_URL = EDX_ROOT_URL + '/signin'
|
||||
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS = (
|
||||
'django.core.context_processors.request',
|
||||
'django.core.context_processors.static',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'django.core.context_processors.i18n',
|
||||
'django.contrib.auth.context_processors.auth', # this is required for admin
|
||||
'django.core.context_processors.csrf',
|
||||
'dealer.contrib.django.staff.context_processor', # access git revision
|
||||
'contentstore.context_processors.doc_url',
|
||||
)
|
||||
|
||||
# use the ratelimit backend to prevent brute force attacks
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'ratelimitbackend.backends.RateLimitModelBackend',
|
||||
@@ -275,12 +300,6 @@ simplefilter('ignore')
|
||||
|
||||
################################# Middleware ###################################
|
||||
|
||||
# List of callables that know how to import templates from various sources.
|
||||
TEMPLATE_LOADERS = (
|
||||
'django.template.loaders.filesystem.Loader',
|
||||
'django.template.loaders.app_directories.Loader',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'request_cache.middleware.RequestCache',
|
||||
'django.middleware.cache.UpdateCacheMiddleware',
|
||||
@@ -304,11 +323,8 @@ MIDDLEWARE_CLASSES = (
|
||||
'embargo.middleware.EmbargoMiddleware',
|
||||
|
||||
# Detects user-requested locale from 'accept-language' header in http request
|
||||
# TODO: Re-import the Django version once we upgrade to Django 1.8 [PLAT-671]
|
||||
# 'django.middleware.locale.LocaleMiddleware',
|
||||
'django_locale.middleware.LocaleMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
|
||||
'django.middleware.transaction.TransactionMiddleware',
|
||||
# needs to run after locale middleware (or anything that modifies the request context)
|
||||
'edxmako.middleware.MakoMiddleware',
|
||||
|
||||
@@ -383,11 +399,12 @@ MODULESTORE = {
|
||||
}
|
||||
|
||||
############################ DJANGO_BUILTINS ################################
|
||||
# Change DEBUG/TEMPLATE_DEBUG in your environment settings files, not here
|
||||
# Change DEBUG in your environment settings files, not here
|
||||
DEBUG = False
|
||||
TEMPLATE_DEBUG = False
|
||||
SESSION_COOKIE_SECURE = False
|
||||
SESSION_SAVE_EVERY_REQUEST = False
|
||||
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
|
||||
|
||||
|
||||
# Site info
|
||||
SITE_ID = 1
|
||||
@@ -704,8 +721,8 @@ INSTALLED_APPS = (
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'djcelery',
|
||||
'south',
|
||||
'method_override',
|
||||
|
||||
# Common views
|
||||
@@ -726,13 +743,14 @@ INSTALLED_APPS = (
|
||||
# For CMS
|
||||
'contentstore',
|
||||
'course_creators',
|
||||
'external_auth',
|
||||
'student', # misleading name due to sharing with lms
|
||||
'openedx.core.djangoapps.course_groups', # not used in cms (yet), but tests run
|
||||
'xblock_config',
|
||||
|
||||
# Tracking
|
||||
'track',
|
||||
'eventtracking.django',
|
||||
'eventtracking.django.apps.EventTrackingConfig',
|
||||
|
||||
# Monitoring
|
||||
'datadog',
|
||||
@@ -740,7 +758,6 @@ INSTALLED_APPS = (
|
||||
# For asset pipelining
|
||||
'edxmako',
|
||||
'pipeline',
|
||||
'django.contrib.staticfiles',
|
||||
'static_replace',
|
||||
'require',
|
||||
|
||||
@@ -793,6 +810,11 @@ INSTALLED_APPS = (
|
||||
|
||||
# Self-paced course configuration
|
||||
'openedx.core.djangoapps.self_paced',
|
||||
|
||||
# These are apps that aren't strictly needed by Studio, but are imported by
|
||||
# other apps that are. Django 1.8 wants to have imported models supported
|
||||
# by installed apps.
|
||||
'lms.djangoapps.verify_student',
|
||||
)
|
||||
|
||||
|
||||
@@ -901,9 +923,6 @@ OPTIONAL_APPS = (
|
||||
|
||||
# milestones
|
||||
'milestones',
|
||||
|
||||
# edX Proctoring
|
||||
'edx_proctoring',
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': ENV_ROOT / "db" / "edx.db",
|
||||
'ATOMIC_REQUESTS': True,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,5 @@ DJKOMBU_POLLING_INTERVAL = 1.0
|
||||
|
||||
# Disable transaction management because we are using a worker. Views
|
||||
# that request a task and wait for the result will deadlock otherwise.
|
||||
|
||||
MIDDLEWARE_CLASSES = tuple(
|
||||
c for c in MIDDLEWARE_CLASSES
|
||||
if c != 'django.middleware.transaction.TransactionMiddleware')
|
||||
|
||||
# Note: other alternatives for disabling transactions don't work in 1.4
|
||||
# https://code.djangoproject.com/ticket/2304
|
||||
# https://code.djangoproject.com/ticket/16039
|
||||
for database_name in DATABASES:
|
||||
DATABASES[database_name]['ATOMIC_REQUESTS'] = False
|
||||
|
||||
@@ -12,7 +12,7 @@ MEDIA_ROOT = "/edx/var/edxapp/uploads"
|
||||
|
||||
DEBUG = True
|
||||
USE_I18N = True
|
||||
TEMPLATE_DEBUG = DEBUG
|
||||
DEFAULT_TEMPLATE_ENGINE['OPTIONS']['debug'] = DEBUG
|
||||
HTTPS = 'off'
|
||||
|
||||
################################ LOGGERS ######################################
|
||||
|
||||
@@ -128,9 +128,14 @@ DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': TEST_ROOT / "db" / "cms.db",
|
||||
'ATOMIC_REQUESTS': True,
|
||||
},
|
||||
}
|
||||
|
||||
# This hack disables migrations during tests. We want to create tables directly from the models for speed.
|
||||
# See https://groups.google.com/d/msg/django-developers/PWPj3etj3-U/kCl6pMsQYYoJ.
|
||||
MIGRATION_MODULES = {app: "app.migrations_not_used_in_tests" for app in INSTALLED_APPS}
|
||||
|
||||
LMS_BASE = "localhost:8000"
|
||||
FEATURES['PREVIEW_LMS_BASE'] = "preview"
|
||||
|
||||
@@ -171,11 +176,8 @@ CACHES = {
|
||||
},
|
||||
}
|
||||
|
||||
# Add external_auth to Installed apps for testing
|
||||
INSTALLED_APPS += ('external_auth', )
|
||||
|
||||
# Add milestones to Installed apps for testing
|
||||
INSTALLED_APPS += ('milestones', 'openedx.core.djangoapps.call_stack_manager')
|
||||
# Add apps to Installed apps for testing
|
||||
INSTALLED_APPS += ('openedx.core.djangoapps.call_stack_manager',)
|
||||
|
||||
# hide ratelimit warnings while running tests
|
||||
filterwarnings('ignore', message='No request passed to the backend, unable to rate-limit')
|
||||
|
||||
@@ -17,6 +17,7 @@ from .common import * # pylint: disable=wildcard-import, unused-wildcard-import
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'ATOMIC_REQUESTS': True,
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
@@ -85,11 +85,6 @@ BROKER_HEARTBEAT_CHECKRATE = 2
|
||||
# Each worker should only fetch one message at a time
|
||||
CELERYD_PREFETCH_MULTIPLIER = 1
|
||||
|
||||
# Skip djcelery migrations, since we don't use the database as the broker
|
||||
SOUTH_MIGRATION_MODULES = {
|
||||
'djcelery': 'ignore',
|
||||
}
|
||||
|
||||
# Rename the exchange and queues for each variant
|
||||
|
||||
QUEUE_VARIANT = CONFIG_PREFIX.lower()
|
||||
|
||||
@@ -8,7 +8,8 @@ from django.conf import settings
|
||||
settings.INSTALLED_APPS # pylint: disable=pointless-statement
|
||||
|
||||
from openedx.core.lib.django_startup import autostartup
|
||||
from monkey_patch import django_utils_translation
|
||||
import django
|
||||
from monkey_patch import third_party_auth
|
||||
|
||||
import xmodule.x_module
|
||||
import cms.lib.xblock.runtime
|
||||
@@ -18,7 +19,9 @@ def run():
|
||||
"""
|
||||
Executed during django startup
|
||||
"""
|
||||
django_utils_translation.patch()
|
||||
third_party_auth.patch()
|
||||
|
||||
django.setup()
|
||||
|
||||
autostartup()
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ from openedx.core.lib.js_utils import (
|
||||
url_name: "${context_course.location.name | h}",
|
||||
org: "${context_course.location.org | h}",
|
||||
num: "${context_course.location.course | h}",
|
||||
display_course_number: "${_(context_course.display_coursenumber)}",
|
||||
display_course_number: "${_(context_course.display_number_with_default)}",
|
||||
revision: "${context_course.location.revision | h}",
|
||||
self_paced: ${escape_json_dumps(context_course.self_paced) | n}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user