From 45b17f8d16214c04225edc9764aac1dcf1eeb688 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Tue, 13 Jan 2026 11:25:41 -0500 Subject: [PATCH 01/11] temp: consolidate learning core app install to api call --- cms/envs/common.py | 9 ++------- lms/envs/common.py | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/cms/envs/common.py b/cms/envs/common.py index ceaa86756caa..482b9c78bf41 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -45,6 +45,7 @@ from datetime import timedelta from django.utils.translation import gettext_lazy as _ +from openedx_learning.api.django import learning_core_apps_to_install from openedx.envs.common import * # pylint: disable=wildcard-import @@ -898,13 +899,7 @@ def make_lms_template_path(settings): 'openedx_events', # Learning Core Apps, used by v2 content libraries (content_libraries app) - "openedx_learning.apps.authoring.collections", - "openedx_learning.apps.authoring.components", - "openedx_learning.apps.authoring.contents", - "openedx_learning.apps.authoring.publishing", - "openedx_learning.apps.authoring.units", - "openedx_learning.apps.authoring.subsections", - "openedx_learning.apps.authoring.sections", + *learning_core_apps_to_install(), ] ### Apps only installed in some instances diff --git a/lms/envs/common.py b/lms/envs/common.py index 0419633f583e..774fed134141 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -60,6 +60,7 @@ PROVISIONING_PENDING_ENTERPRISE_CUSTOMER_ADMIN_ROLE, DEFAULT_ENTERPRISE_ENROLLMENT_INTENTIONS_ROLE, ) +from openedx_learning.api.django import learning_core_apps_to_install from openedx.core.lib.derived import Derived from openedx.envs.common import * # pylint: disable=wildcard-import @@ -2020,13 +2021,7 @@ 'openedx_events', # Learning Core Apps, used by v2 content libraries (content_libraries app) - "openedx_learning.apps.authoring.collections", - "openedx_learning.apps.authoring.components", - "openedx_learning.apps.authoring.contents", - "openedx_learning.apps.authoring.publishing", - "openedx_learning.apps.authoring.units", - "openedx_learning.apps.authoring.subsections", - "openedx_learning.apps.authoring.sections", + *learning_core_apps_to_install(), ] # Add LMS specific optional apps From d9af181d75d385421b59ccc5013353ab49e64784 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Tue, 13 Jan 2026 14:26:21 -0500 Subject: [PATCH 02/11] refactor: rewrite some history to pretend the learning core models were always in oel_authoring --- ...learningcontextlinksstatus_publishableentitylink.py | 2 +- .../migrations/0010_container_link_models.py | 4 ++-- .../modulestore_migrator/migrations/0001_initial.py | 10 +++++----- ...005_modulestoreblockmigration_unsupported_reason.py | 2 +- .../0010_contentlibrary_learning_package_and_more.py | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py b/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py index 84b80cd63359..783f5a6a2457 100644 --- a/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py +++ b/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py @@ -81,7 +81,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', - to='oel_publishing.publishableentity', + to='oel_authoring.publishableentity', ), ), ], diff --git a/cms/djangoapps/contentstore/migrations/0010_container_link_models.py b/cms/djangoapps/contentstore/migrations/0010_container_link_models.py index 8d42ad96145d..c54c0f1e9592 100644 --- a/cms/djangoapps/contentstore/migrations/0010_container_link_models.py +++ b/cms/djangoapps/contentstore/migrations/0010_container_link_models.py @@ -32,7 +32,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', - to='oel_components.component', + to='oel_authoring.component', ), ), migrations.CreateModel( @@ -48,7 +48,7 @@ class Migration(migrations.Migration): ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), ('updated', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), ('upstream_container_key', opaque_keys.edx.django.models.ContainerKeyField(help_text='Upstream block key (e.g. lct:...), this value cannot be null and is useful to track upstream library blocks that do not exist yet or were deleted.', max_length=255)), - ('upstream_container', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='oel_publishing.container')), + ('upstream_container', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='oel_authoring.container')), ], options={ 'abstract': False, diff --git a/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py b/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py index 42d1df5bad1b..de4b6609c85a 100644 --- a/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py +++ b/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py @@ -25,7 +25,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('change_log_record', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_publishing.draftchangelogrecord')), + ('change_log_record', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.draftchangelogrecord')), ], ), migrations.CreateModel( @@ -36,7 +36,7 @@ class Migration(migrations.Migration): ('composition_level', models.CharField(choices=[('component', 'Component'), ('unit', 'Unit'), ('subsection', 'Subsection'), ('section', 'Section')], default='component', help_text='Maximum hierachy level at which content should be aggregated in target library', max_length=255)), ('repeat_handling_strategy', models.CharField(choices=[('skip', 'Skip'), ('fork', 'Fork'), ('update', 'Update')], default='skip', help_text='If a piece of content already exists in the content library, choose how to handle it.', max_length=24)), ('preserve_url_slugs', models.BooleanField(default=False, help_text='Should the migration preserve the location IDs of the existing blocks?If not, then new, unique human-readable IDs will be generated based on the block titles.')), - ('change_log', models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_publishing.draftchangelog')), + ('change_log', models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.draftchangelog')), ], ), migrations.CreateModel( @@ -60,12 +60,12 @@ class Migration(migrations.Migration): migrations.AddField( model_name='modulestoremigration', name='target', - field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.learningpackage'), + field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.learningpackage'), ), migrations.AddField( model_name='modulestoremigration', name='target_collection', - field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_collections.collection'), + field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.collection'), ), migrations.AddField( model_name='modulestoremigration', @@ -99,7 +99,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='modulestoreblockmigration', name='target', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.publishableentity'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.publishableentity'), ), migrations.AlterUniqueTogether( name='modulestoreblockmigration', diff --git a/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py b/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py index f043e208dc35..47d03e2ffb69 100644 --- a/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py +++ b/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py @@ -19,7 +19,7 @@ class Migration(migrations.Migration): help_text='The target entity of this block migration, set to null if it fails to migrate', null=True, on_delete=django.db.models.deletion.CASCADE, - to='oel_publishing.publishableentity', + to='oel_authoring.publishableentity', ), ), migrations.AddField( diff --git a/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py b/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py index 372f51de310c..d67c64bf9157 100644 --- a/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py +++ b/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py @@ -15,7 +15,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='contentlibrary', name='learning_package', - field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.learningpackage'), + field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.learningpackage'), ), migrations.AlterField( model_name='contentlibrary', From 188774d0de620fa16a0bc38d0ca0fba3ca2646a0 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Wed, 21 Jan 2026 20:18:53 -0500 Subject: [PATCH 03/11] temp: remove migration history rewriting, since we're keeping the old apps around --- ...learningcontextlinksstatus_publishableentitylink.py | 2 +- .../migrations/0010_container_link_models.py | 4 ++-- .../modulestore_migrator/migrations/0001_initial.py | 10 +++++----- ...005_modulestoreblockmigration_unsupported_reason.py | 2 +- .../0010_contentlibrary_learning_package_and_more.py | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py b/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py index 783f5a6a2457..84b80cd63359 100644 --- a/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py +++ b/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py @@ -81,7 +81,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', - to='oel_authoring.publishableentity', + to='oel_publishing.publishableentity', ), ), ], diff --git a/cms/djangoapps/contentstore/migrations/0010_container_link_models.py b/cms/djangoapps/contentstore/migrations/0010_container_link_models.py index c54c0f1e9592..8d42ad96145d 100644 --- a/cms/djangoapps/contentstore/migrations/0010_container_link_models.py +++ b/cms/djangoapps/contentstore/migrations/0010_container_link_models.py @@ -32,7 +32,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', - to='oel_authoring.component', + to='oel_components.component', ), ), migrations.CreateModel( @@ -48,7 +48,7 @@ class Migration(migrations.Migration): ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), ('updated', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), ('upstream_container_key', opaque_keys.edx.django.models.ContainerKeyField(help_text='Upstream block key (e.g. lct:...), this value cannot be null and is useful to track upstream library blocks that do not exist yet or were deleted.', max_length=255)), - ('upstream_container', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='oel_authoring.container')), + ('upstream_container', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='oel_publishing.container')), ], options={ 'abstract': False, diff --git a/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py b/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py index de4b6609c85a..42d1df5bad1b 100644 --- a/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py +++ b/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py @@ -25,7 +25,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('change_log_record', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.draftchangelogrecord')), + ('change_log_record', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_publishing.draftchangelogrecord')), ], ), migrations.CreateModel( @@ -36,7 +36,7 @@ class Migration(migrations.Migration): ('composition_level', models.CharField(choices=[('component', 'Component'), ('unit', 'Unit'), ('subsection', 'Subsection'), ('section', 'Section')], default='component', help_text='Maximum hierachy level at which content should be aggregated in target library', max_length=255)), ('repeat_handling_strategy', models.CharField(choices=[('skip', 'Skip'), ('fork', 'Fork'), ('update', 'Update')], default='skip', help_text='If a piece of content already exists in the content library, choose how to handle it.', max_length=24)), ('preserve_url_slugs', models.BooleanField(default=False, help_text='Should the migration preserve the location IDs of the existing blocks?If not, then new, unique human-readable IDs will be generated based on the block titles.')), - ('change_log', models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.draftchangelog')), + ('change_log', models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_publishing.draftchangelog')), ], ), migrations.CreateModel( @@ -60,12 +60,12 @@ class Migration(migrations.Migration): migrations.AddField( model_name='modulestoremigration', name='target', - field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.learningpackage'), + field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.learningpackage'), ), migrations.AddField( model_name='modulestoremigration', name='target_collection', - field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.collection'), + field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_collections.collection'), ), migrations.AddField( model_name='modulestoremigration', @@ -99,7 +99,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='modulestoreblockmigration', name='target', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.publishableentity'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.publishableentity'), ), migrations.AlterUniqueTogether( name='modulestoreblockmigration', diff --git a/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py b/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py index 47d03e2ffb69..f043e208dc35 100644 --- a/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py +++ b/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py @@ -19,7 +19,7 @@ class Migration(migrations.Migration): help_text='The target entity of this block migration, set to null if it fails to migrate', null=True, on_delete=django.db.models.deletion.CASCADE, - to='oel_authoring.publishableentity', + to='oel_publishing.publishableentity', ), ), migrations.AddField( diff --git a/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py b/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py index d67c64bf9157..372f51de310c 100644 --- a/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py +++ b/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py @@ -15,7 +15,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='contentlibrary', name='learning_package', - field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.learningpackage'), + field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.learningpackage'), ), migrations.AlterField( model_name='contentlibrary', From 8402e5cd1fbb745534f084fb21daa01c94e27cf9 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Thu, 22 Jan 2026 00:06:43 -0500 Subject: [PATCH 04/11] temp: move all dependencies to assume oel_authoring --- ...rningcontextlinksstatus_publishableentitylink.py | 4 ++-- .../migrations/0010_container_link_models.py | 7 +++---- .../modulestore_migrator/migrations/0001_initial.py | 13 ++++++------- ..._modulestoreblockmigration_unsupported_reason.py | 4 ++-- ...0010_contentlibrary_learning_package_and_more.py | 4 ++-- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py b/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py index 84b80cd63359..97b26115f0df 100644 --- a/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py +++ b/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py @@ -11,7 +11,7 @@ class Migration(migrations.Migration): dependencies = [ - ('oel_publishing', '0002_alter_learningpackage_key_and_more'), + ('oel_authoring', '0001_initial'), ('contentstore', '0008_cleanstalecertificateavailabilitydatesconfig'), ] @@ -81,7 +81,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', - to='oel_publishing.publishableentity', + to='oel_authoring.publishableentity', ), ), ], diff --git a/cms/djangoapps/contentstore/migrations/0010_container_link_models.py b/cms/djangoapps/contentstore/migrations/0010_container_link_models.py index 8d42ad96145d..5e7f7a0ea2a5 100644 --- a/cms/djangoapps/contentstore/migrations/0010_container_link_models.py +++ b/cms/djangoapps/contentstore/migrations/0010_container_link_models.py @@ -10,8 +10,7 @@ class Migration(migrations.Migration): dependencies = [ - ('oel_publishing', '0003_containers'), - ('oel_components', '0003_remove_componentversioncontent_learner_downloadable'), + ('oel_authoring', '0001_initial'), ('contentstore', '0009_learningcontextlinksstatus_publishableentitylink'), ] @@ -32,7 +31,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', - to='oel_components.component', + to='oel_authoring.component', ), ), migrations.CreateModel( @@ -48,7 +47,7 @@ class Migration(migrations.Migration): ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), ('updated', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), ('upstream_container_key', opaque_keys.edx.django.models.ContainerKeyField(help_text='Upstream block key (e.g. lct:...), this value cannot be null and is useful to track upstream library blocks that do not exist yet or were deleted.', max_length=255)), - ('upstream_container', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='oel_publishing.container')), + ('upstream_container', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='oel_authoring.container')), ], options={ 'abstract': False, diff --git a/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py b/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py index 42d1df5bad1b..3cbff1b3f973 100644 --- a/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py +++ b/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py @@ -13,8 +13,7 @@ class Migration(migrations.Migration): dependencies = [ ('content_staging', '0006_alter_userclipboard_source_usage_key'), - ('oel_collections', '0005_alter_collection_options_alter_collection_enabled'), - ('oel_publishing', '0008_alter_draftchangelogrecord_options_and_more'), + ('oel_authoring', '0001_initial'), ('user_tasks', '0004_url_textfield'), ] @@ -25,7 +24,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('change_log_record', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_publishing.draftchangelogrecord')), + ('change_log_record', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.draftchangelogrecord')), ], ), migrations.CreateModel( @@ -36,7 +35,7 @@ class Migration(migrations.Migration): ('composition_level', models.CharField(choices=[('component', 'Component'), ('unit', 'Unit'), ('subsection', 'Subsection'), ('section', 'Section')], default='component', help_text='Maximum hierachy level at which content should be aggregated in target library', max_length=255)), ('repeat_handling_strategy', models.CharField(choices=[('skip', 'Skip'), ('fork', 'Fork'), ('update', 'Update')], default='skip', help_text='If a piece of content already exists in the content library, choose how to handle it.', max_length=24)), ('preserve_url_slugs', models.BooleanField(default=False, help_text='Should the migration preserve the location IDs of the existing blocks?If not, then new, unique human-readable IDs will be generated based on the block titles.')), - ('change_log', models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_publishing.draftchangelog')), + ('change_log', models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.draftchangelog')), ], ), migrations.CreateModel( @@ -60,12 +59,12 @@ class Migration(migrations.Migration): migrations.AddField( model_name='modulestoremigration', name='target', - field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.learningpackage'), + field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.learningpackage'), ), migrations.AddField( model_name='modulestoremigration', name='target_collection', - field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_collections.collection'), + field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.collection'), ), migrations.AddField( model_name='modulestoremigration', @@ -99,7 +98,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='modulestoreblockmigration', name='target', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.publishableentity'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.publishableentity'), ), migrations.AlterUniqueTogether( name='modulestoreblockmigration', diff --git a/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py b/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py index f043e208dc35..e872f971cf24 100644 --- a/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py +++ b/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ ('modulestore_migrator', '0003_modulestoremigration_is_failed'), - ('oel_publishing', '0008_alter_draftchangelogrecord_options_and_more'), + ('oel_authoring', '0001_initial'), ] operations = [ @@ -19,7 +19,7 @@ class Migration(migrations.Migration): help_text='The target entity of this block migration, set to null if it fails to migrate', null=True, on_delete=django.db.models.deletion.CASCADE, - to='oel_publishing.publishableentity', + to='oel_authoring.publishableentity', ), ), migrations.AddField( diff --git a/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py b/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py index 372f51de310c..3ceefc221987 100644 --- a/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py +++ b/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ - ('oel_publishing', '0001_initial'), + ('oel_authoring', '0001_initial'), ('content_libraries', '0009_alter_contentlibrary_authorized_lti_configs'), ] @@ -15,7 +15,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='contentlibrary', name='learning_package', - field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.learningpackage'), + field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.learningpackage'), ), migrations.AlterField( model_name='contentlibrary', From cddb3a07b42ca08cfe048e8ad232a470c756c24e Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Thu, 22 Jan 2026 14:19:56 -0500 Subject: [PATCH 05/11] temp: revert temp: move all dependencies to assume oel_authoring This reverts commit 5706f208877a4ff3d250314e8e9d3aa0051eeee7. --- ...rningcontextlinksstatus_publishableentitylink.py | 4 ++-- .../migrations/0010_container_link_models.py | 7 ++++--- .../modulestore_migrator/migrations/0001_initial.py | 13 +++++++------ ..._modulestoreblockmigration_unsupported_reason.py | 4 ++-- ...0010_contentlibrary_learning_package_and_more.py | 4 ++-- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py b/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py index 97b26115f0df..84b80cd63359 100644 --- a/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py +++ b/cms/djangoapps/contentstore/migrations/0009_learningcontextlinksstatus_publishableentitylink.py @@ -11,7 +11,7 @@ class Migration(migrations.Migration): dependencies = [ - ('oel_authoring', '0001_initial'), + ('oel_publishing', '0002_alter_learningpackage_key_and_more'), ('contentstore', '0008_cleanstalecertificateavailabilitydatesconfig'), ] @@ -81,7 +81,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', - to='oel_authoring.publishableentity', + to='oel_publishing.publishableentity', ), ), ], diff --git a/cms/djangoapps/contentstore/migrations/0010_container_link_models.py b/cms/djangoapps/contentstore/migrations/0010_container_link_models.py index 5e7f7a0ea2a5..8d42ad96145d 100644 --- a/cms/djangoapps/contentstore/migrations/0010_container_link_models.py +++ b/cms/djangoapps/contentstore/migrations/0010_container_link_models.py @@ -10,7 +10,8 @@ class Migration(migrations.Migration): dependencies = [ - ('oel_authoring', '0001_initial'), + ('oel_publishing', '0003_containers'), + ('oel_components', '0003_remove_componentversioncontent_learner_downloadable'), ('contentstore', '0009_learningcontextlinksstatus_publishableentitylink'), ] @@ -31,7 +32,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', - to='oel_authoring.component', + to='oel_components.component', ), ), migrations.CreateModel( @@ -47,7 +48,7 @@ class Migration(migrations.Migration): ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), ('updated', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), ('upstream_container_key', opaque_keys.edx.django.models.ContainerKeyField(help_text='Upstream block key (e.g. lct:...), this value cannot be null and is useful to track upstream library blocks that do not exist yet or were deleted.', max_length=255)), - ('upstream_container', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='oel_authoring.container')), + ('upstream_container', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='oel_publishing.container')), ], options={ 'abstract': False, diff --git a/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py b/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py index 3cbff1b3f973..42d1df5bad1b 100644 --- a/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py +++ b/cms/djangoapps/modulestore_migrator/migrations/0001_initial.py @@ -13,7 +13,8 @@ class Migration(migrations.Migration): dependencies = [ ('content_staging', '0006_alter_userclipboard_source_usage_key'), - ('oel_authoring', '0001_initial'), + ('oel_collections', '0005_alter_collection_options_alter_collection_enabled'), + ('oel_publishing', '0008_alter_draftchangelogrecord_options_and_more'), ('user_tasks', '0004_url_textfield'), ] @@ -24,7 +25,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('change_log_record', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.draftchangelogrecord')), + ('change_log_record', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_publishing.draftchangelogrecord')), ], ), migrations.CreateModel( @@ -35,7 +36,7 @@ class Migration(migrations.Migration): ('composition_level', models.CharField(choices=[('component', 'Component'), ('unit', 'Unit'), ('subsection', 'Subsection'), ('section', 'Section')], default='component', help_text='Maximum hierachy level at which content should be aggregated in target library', max_length=255)), ('repeat_handling_strategy', models.CharField(choices=[('skip', 'Skip'), ('fork', 'Fork'), ('update', 'Update')], default='skip', help_text='If a piece of content already exists in the content library, choose how to handle it.', max_length=24)), ('preserve_url_slugs', models.BooleanField(default=False, help_text='Should the migration preserve the location IDs of the existing blocks?If not, then new, unique human-readable IDs will be generated based on the block titles.')), - ('change_log', models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.draftchangelog')), + ('change_log', models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_publishing.draftchangelog')), ], ), migrations.CreateModel( @@ -59,12 +60,12 @@ class Migration(migrations.Migration): migrations.AddField( model_name='modulestoremigration', name='target', - field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.learningpackage'), + field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.learningpackage'), ), migrations.AddField( model_name='modulestoremigration', name='target_collection', - field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.collection'), + field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_collections.collection'), ), migrations.AddField( model_name='modulestoremigration', @@ -98,7 +99,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='modulestoreblockmigration', name='target', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.publishableentity'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.publishableentity'), ), migrations.AlterUniqueTogether( name='modulestoreblockmigration', diff --git a/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py b/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py index e872f971cf24..f043e208dc35 100644 --- a/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py +++ b/cms/djangoapps/modulestore_migrator/migrations/0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason.py @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ ('modulestore_migrator', '0003_modulestoremigration_is_failed'), - ('oel_authoring', '0001_initial'), + ('oel_publishing', '0008_alter_draftchangelogrecord_options_and_more'), ] operations = [ @@ -19,7 +19,7 @@ class Migration(migrations.Migration): help_text='The target entity of this block migration, set to null if it fails to migrate', null=True, on_delete=django.db.models.deletion.CASCADE, - to='oel_authoring.publishableentity', + to='oel_publishing.publishableentity', ), ), migrations.AddField( diff --git a/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py b/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py index 3ceefc221987..372f51de310c 100644 --- a/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py +++ b/openedx/core/djangoapps/content_libraries/migrations/0010_contentlibrary_learning_package_and_more.py @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ - ('oel_authoring', '0001_initial'), + ('oel_publishing', '0001_initial'), ('content_libraries', '0009_alter_contentlibrary_authorized_lti_configs'), ] @@ -15,7 +15,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='contentlibrary', name='learning_package', - field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.learningpackage'), + field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.learningpackage'), ), migrations.AlterField( model_name='contentlibrary', From 811126ddb4da2e9f5c512c722deef7e9b27b22a8 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Sun, 25 Jan 2026 14:46:05 -0500 Subject: [PATCH 06/11] temp: one-to-one field must be updated --- ...2_alter_contentlibrary_learning_package.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py diff --git a/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py b/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py new file mode 100644 index 000000000000..9a6c838eecdd --- /dev/null +++ b/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py @@ -0,0 +1,20 @@ +# Generated by Django 5.2.9 on 2026-01-25 19:44 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('content_libraries', '0011_remove_contentlibrary_bundle_uuid_and_more'), + ('oel_authoring', '0002_rename_tables_to_oel_authoring'), + ] + + operations = [ + migrations.AlterField( + model_name='contentlibrary', + name='learning_package', + field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.learningpackage'), + ), + ] From 219c5c5d9785f042399a4a6d145bc5ecf612bfc4 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Tue, 27 Jan 2026 16:56:11 -0500 Subject: [PATCH 07/11] fix: prevent migration ordering inconsistencies --- ...r_componentlink_upstream_block_and_more.py | 31 +++++++++++++ ...ockmigration_change_log_record_and_more.py | 46 +++++++++++++++++++ cms/envs/common.py | 5 +- lms/envs/common.py | 26 +++++++++-- ...2_alter_contentlibrary_learning_package.py | 16 +++++-- 5 files changed, 113 insertions(+), 11 deletions(-) create mode 100644 cms/djangoapps/contentstore/migrations/0015_alter_componentlink_upstream_block_and_more.py create mode 100644 cms/djangoapps/modulestore_migrator/migrations/0007_alter_modulestoreblockmigration_change_log_record_and_more.py diff --git a/cms/djangoapps/contentstore/migrations/0015_alter_componentlink_upstream_block_and_more.py b/cms/djangoapps/contentstore/migrations/0015_alter_componentlink_upstream_block_and_more.py new file mode 100644 index 000000000000..bc203f5e52c8 --- /dev/null +++ b/cms/djangoapps/contentstore/migrations/0015_alter_componentlink_upstream_block_and_more.py @@ -0,0 +1,31 @@ +# Generated by Django 5.2.10 on 2026-01-25 21:52 + +import django.db.models.deletion +from django.db import migrations, models +from django.db.migrations.operations.special import SeparateDatabaseAndState + + +class Migration(migrations.Migration): + + dependencies = [ + ('contentstore', '0014_remove_componentlink_downstream_is_modified_and_more'), + ('oel_authoring', '0001_initial'), + ] + + operations = [ + SeparateDatabaseAndState( + database_operations=[], + state_operations=[ + migrations.AlterField( + model_name='componentlink', + name='upstream_block', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='oel_authoring.component'), + ), + migrations.AlterField( + model_name='containerlink', + name='upstream_container', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='oel_authoring.container'), + ), + ] + ), + ] diff --git a/cms/djangoapps/modulestore_migrator/migrations/0007_alter_modulestoreblockmigration_change_log_record_and_more.py b/cms/djangoapps/modulestore_migrator/migrations/0007_alter_modulestoreblockmigration_change_log_record_and_more.py new file mode 100644 index 000000000000..191913c301b9 --- /dev/null +++ b/cms/djangoapps/modulestore_migrator/migrations/0007_alter_modulestoreblockmigration_change_log_record_and_more.py @@ -0,0 +1,46 @@ +# Generated by Django 5.2.10 on 2026-01-25 21:52 + +import django.db.models.deletion +from django.db import migrations, models +from django.db.migrations.operations.special import SeparateDatabaseAndState + + +class Migration(migrations.Migration): + + dependencies = [ + ('modulestore_migrator', '0006_alter_modulestoreblocksource_forwarded_and_more'), + ('oel_authoring', '0001_initial'), + ] + + operations = [ + SeparateDatabaseAndState( + database_operations=[], + state_operations=[ + migrations.AlterField( + model_name='modulestoreblockmigration', + name='change_log_record', + field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.draftchangelogrecord'), + ), + migrations.AlterField( + model_name='modulestoreblockmigration', + name='target', + field=models.ForeignKey(blank=True, help_text='The target entity of this block migration, set to null if it fails to migrate', null=True, on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.publishableentity'), + ), + migrations.AlterField( + model_name='modulestoremigration', + name='change_log', + field=models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.draftchangelog'), + ), + migrations.AlterField( + model_name='modulestoremigration', + name='target', + field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.learningpackage'), + ), + migrations.AlterField( + model_name='modulestoremigration', + name='target_collection', + field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.collection'), + ), + ] + ), + ] diff --git a/cms/envs/common.py b/cms/envs/common.py index 482b9c78bf41..f0371952f833 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -45,7 +45,7 @@ from datetime import timedelta from django.utils.translation import gettext_lazy as _ -from openedx_learning.api.django import learning_core_apps_to_install +from openedx_learning.api.django import openedx_learning_apps_to_install from openedx.envs.common import * # pylint: disable=wildcard-import @@ -898,8 +898,7 @@ def make_lms_template_path(settings): 'openedx_events', - # Learning Core Apps, used by v2 content libraries (content_libraries app) - *learning_core_apps_to_install(), + *openedx_learning_apps_to_install(), ] ### Apps only installed in some instances diff --git a/lms/envs/common.py b/lms/envs/common.py index 774fed134141..254e967acb48 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -60,7 +60,7 @@ PROVISIONING_PENDING_ENTERPRISE_CUSTOMER_ADMIN_ROLE, DEFAULT_ENTERPRISE_ENROLLMENT_INTENTIONS_ROLE, ) -from openedx_learning.api.django import learning_core_apps_to_install +from openedx_learning.api.django import openedx_learning_apps_to_install from openedx.core.lib.derived import Derived from openedx.envs.common import * # pylint: disable=wildcard-import @@ -2020,8 +2020,12 @@ 'openedx_events', - # Learning Core Apps, used by v2 content libraries (content_libraries app) - *learning_core_apps_to_install(), + # These go together as a unit. + *openedx_learning_apps_to_install(), + 'cms.djangoapps.contentstore', + 'cms.djangoapps.modulestore_migrator', + 'openedx.core.djangoapps.content.search', + 'openedx.core.djangoapps.content_staging', ] # Add LMS specific optional apps @@ -2875,9 +2879,25 @@ from edx_django_utils.plugins import get_plugin_apps, add_plugins # pylint: disable=wrong-import-position,wrong-import-order from openedx.core.djangoapps.plugins.constants import ProjectType, SettingsType # pylint: disable=wrong-import-position + +for app in INSTALLED_APPS: + if 'content_libraries' in app: + print("Found it before plugin application!") + INSTALLED_APPS.extend(get_plugin_apps(ProjectType.LMS)) + +for app in INSTALLED_APPS: + if 'content_libraries' in app: + print("Found it after extension!") + + add_plugins(__name__, ProjectType.LMS, SettingsType.COMMON) +for app in INSTALLED_APPS: + if 'content_libraries' in app: + print("Found it after plugin application!") + + PROCTORED_EXAM_VIEWABLE_PAST_DUE = False ######################### rate limit for yt_video_metadata api ############## diff --git a/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py b/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py index 9a6c838eecdd..5ce65f1c7a6d 100644 --- a/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py +++ b/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py @@ -2,19 +2,25 @@ import django.db.models.deletion from django.db import migrations, models +from django.db.migrations.operations.special import SeparateDatabaseAndState class Migration(migrations.Migration): dependencies = [ ('content_libraries', '0011_remove_contentlibrary_bundle_uuid_and_more'), - ('oel_authoring', '0002_rename_tables_to_oel_authoring'), + ('oel_authoring', '0001_initial'), ] operations = [ - migrations.AlterField( - model_name='contentlibrary', - name='learning_package', - field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.learningpackage'), + SeparateDatabaseAndState( + database_operations=[], + state_operations=[ + migrations.AlterField( + model_name='contentlibrary', + name='learning_package', + field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.learningpackage'), + ), + ] ), ] From a85bec57f0130c7521a87aca48979d17c3c19ce7 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Tue, 27 Jan 2026 17:11:13 -0500 Subject: [PATCH 08/11] refactor: change oel_authoring references to be openedx_content --- ...lter_componentlink_upstream_block_and_more.py | 6 +++--- ...eblockmigration_change_log_record_and_more.py | 12 ++++++------ lms/envs/common.py | 16 ---------------- ...0012_alter_contentlibrary_learning_package.py | 4 ++-- 4 files changed, 11 insertions(+), 27 deletions(-) diff --git a/cms/djangoapps/contentstore/migrations/0015_alter_componentlink_upstream_block_and_more.py b/cms/djangoapps/contentstore/migrations/0015_alter_componentlink_upstream_block_and_more.py index bc203f5e52c8..b57da0da34f1 100644 --- a/cms/djangoapps/contentstore/migrations/0015_alter_componentlink_upstream_block_and_more.py +++ b/cms/djangoapps/contentstore/migrations/0015_alter_componentlink_upstream_block_and_more.py @@ -9,7 +9,7 @@ class Migration(migrations.Migration): dependencies = [ ('contentstore', '0014_remove_componentlink_downstream_is_modified_and_more'), - ('oel_authoring', '0001_initial'), + ('openedx_content', '0001_initial'), ] operations = [ @@ -19,12 +19,12 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='componentlink', name='upstream_block', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='oel_authoring.component'), + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='openedx_content.component'), ), migrations.AlterField( model_name='containerlink', name='upstream_container', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='oel_authoring.container'), + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='openedx_content.container'), ), ] ), diff --git a/cms/djangoapps/modulestore_migrator/migrations/0007_alter_modulestoreblockmigration_change_log_record_and_more.py b/cms/djangoapps/modulestore_migrator/migrations/0007_alter_modulestoreblockmigration_change_log_record_and_more.py index 191913c301b9..c5b504b6ae67 100644 --- a/cms/djangoapps/modulestore_migrator/migrations/0007_alter_modulestoreblockmigration_change_log_record_and_more.py +++ b/cms/djangoapps/modulestore_migrator/migrations/0007_alter_modulestoreblockmigration_change_log_record_and_more.py @@ -9,7 +9,7 @@ class Migration(migrations.Migration): dependencies = [ ('modulestore_migrator', '0006_alter_modulestoreblocksource_forwarded_and_more'), - ('oel_authoring', '0001_initial'), + ('openedx_content', '0001_initial'), ] operations = [ @@ -19,27 +19,27 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='modulestoreblockmigration', name='change_log_record', - field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.draftchangelogrecord'), + field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='openedx_content.draftchangelogrecord'), ), migrations.AlterField( model_name='modulestoreblockmigration', name='target', - field=models.ForeignKey(blank=True, help_text='The target entity of this block migration, set to null if it fails to migrate', null=True, on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.publishableentity'), + field=models.ForeignKey(blank=True, help_text='The target entity of this block migration, set to null if it fails to migrate', null=True, on_delete=django.db.models.deletion.CASCADE, to='openedx_content.publishableentity'), ), migrations.AlterField( model_name='modulestoremigration', name='change_log', - field=models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.draftchangelog'), + field=models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='openedx_content.draftchangelog'), ), migrations.AlterField( model_name='modulestoremigration', name='target', - field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.learningpackage'), + field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='openedx_content.learningpackage'), ), migrations.AlterField( model_name='modulestoremigration', name='target_collection', - field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.collection'), + field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='openedx_content.collection'), ), ] ), diff --git a/lms/envs/common.py b/lms/envs/common.py index 254e967acb48..2d46827658a5 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -2879,25 +2879,9 @@ from edx_django_utils.plugins import get_plugin_apps, add_plugins # pylint: disable=wrong-import-position,wrong-import-order from openedx.core.djangoapps.plugins.constants import ProjectType, SettingsType # pylint: disable=wrong-import-position - -for app in INSTALLED_APPS: - if 'content_libraries' in app: - print("Found it before plugin application!") - INSTALLED_APPS.extend(get_plugin_apps(ProjectType.LMS)) - -for app in INSTALLED_APPS: - if 'content_libraries' in app: - print("Found it after extension!") - - add_plugins(__name__, ProjectType.LMS, SettingsType.COMMON) -for app in INSTALLED_APPS: - if 'content_libraries' in app: - print("Found it after plugin application!") - - PROCTORED_EXAM_VIEWABLE_PAST_DUE = False ######################### rate limit for yt_video_metadata api ############## diff --git a/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py b/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py index 5ce65f1c7a6d..774875597bc1 100644 --- a/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py +++ b/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py @@ -9,7 +9,7 @@ class Migration(migrations.Migration): dependencies = [ ('content_libraries', '0011_remove_contentlibrary_bundle_uuid_and_more'), - ('oel_authoring', '0001_initial'), + ('openedx_content', '0001_initial'), ] operations = [ @@ -19,7 +19,7 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='contentlibrary', name='learning_package', - field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.learningpackage'), + field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='openedx_content.learningpackage'), ), ] ), From 5e4e5745d4195489e499532cb64ba9992320fc7f Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Wed, 28 Jan 2026 01:04:07 -0500 Subject: [PATCH 09/11] temp: adjust requirements to pull in my branch for testing --- lms/envs/common.py | 5 ++++- requirements/constraints.txt | 2 +- requirements/edx/base.txt | 2 +- requirements/edx/development.txt | 2 +- requirements/edx/doc.txt | 2 +- requirements/edx/testing.txt | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lms/envs/common.py b/lms/envs/common.py index 2d46827658a5..935bfb6d973e 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -2020,7 +2020,10 @@ 'openedx_events', - # These go together as a unit. + # The openedx_learning apps require contentstore, modulestore_migrator, + # content.search, and content_staging to be in INSTALLED_APPS. If they are + # not here and LMS migrations are run before CMS migrations, it will cause + # errors (certain openedx_learning apps ) *openedx_learning_apps_to_install(), 'cms.djangoapps.contentstore', 'cms.djangoapps.modulestore_migrator', diff --git a/requirements/constraints.txt b/requirements/constraints.txt index d4b7fcb7cf46..838cf59af85b 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -63,7 +63,7 @@ numpy<2.0.0 # Date: 2023-09-18 # pinning this version to avoid updates while the library is being developed # Issue for unpinning: https://github.com/openedx/edx-platform/issues/35269 -openedx-learning==0.30.2 +openedx-learning==git+https://github.com/ormsbee/openedx-learning.git@big-authoring # Date: 2023-11-29 # Open AI version 1.0.0 dropped support for openai.ChatCompletion which is currently in use in enterprise. diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index d59b577a21dc..64a0acf2416c 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -834,7 +834,7 @@ openedx-filters==2.1.0 # ora2 openedx-forum==0.4.0 # via -r requirements/edx/kernel.in -openedx-learning==0.30.2 +openedx-learning==git+https://github.com/ormsbee/openedx-learning.git@big-authoring # via # -c requirements/constraints.txt # -r requirements/edx/kernel.in diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index b24c0fb4bebe..505e61d89fe3 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -1404,7 +1404,7 @@ openedx-forum==0.4.0 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -openedx-learning==0.30.2 +openedx-learning==git+https://github.com/ormsbee/openedx-learning.git@big-authoring # via # -c requirements/constraints.txt # -r requirements/edx/doc.txt diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index c721a39e06fb..f323574a0376 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -1013,7 +1013,7 @@ openedx-filters==2.1.0 # ora2 openedx-forum==0.4.0 # via -r requirements/edx/base.txt -openedx-learning==0.30.2 +openedx-learning==git+https://github.com/ormsbee/openedx-learning.git@big-authoring # via # -c requirements/constraints.txt # -r requirements/edx/base.txt diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index 20cf145c3c2a..a6fccf0a251e 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -1063,7 +1063,7 @@ openedx-filters==2.1.0 # ora2 openedx-forum==0.4.0 # via -r requirements/edx/base.txt -openedx-learning==0.30.2 +openedx-learning==git+https://github.com/ormsbee/openedx-learning.git@big-authoring # via # -c requirements/constraints.txt # -r requirements/edx/base.txt From 81adb60d1489f95a60cd05fdc7952ac70cf87224 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Wed, 28 Jan 2026 01:14:01 -0500 Subject: [PATCH 10/11] temp: try to install from branch, again --- requirements/constraints.txt | 2 +- requirements/edx/base.txt | 2 +- requirements/edx/development.txt | 2 +- requirements/edx/doc.txt | 2 +- requirements/edx/testing.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 838cf59af85b..39d038294c80 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -63,7 +63,7 @@ numpy<2.0.0 # Date: 2023-09-18 # pinning this version to avoid updates while the library is being developed # Issue for unpinning: https://github.com/openedx/edx-platform/issues/35269 -openedx-learning==git+https://github.com/ormsbee/openedx-learning.git@big-authoring +# openedx-learning==0.30.1 # Date: 2023-11-29 # Open AI version 1.0.0 dropped support for openai.ChatCompletion which is currently in use in enterprise. diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 64a0acf2416c..fa1d48847408 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -834,7 +834,7 @@ openedx-filters==2.1.0 # ora2 openedx-forum==0.4.0 # via -r requirements/edx/kernel.in -openedx-learning==git+https://github.com/ormsbee/openedx-learning.git@big-authoring +git+https://github.com/ormsbee/openedx-learning.git@big-authoring#egg=openedx_learning # via # -c requirements/constraints.txt # -r requirements/edx/kernel.in diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index 505e61d89fe3..88a39e5c2ea1 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -1404,7 +1404,7 @@ openedx-forum==0.4.0 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -openedx-learning==git+https://github.com/ormsbee/openedx-learning.git@big-authoring +git+https://github.com/ormsbee/openedx-learning.git@big-authoring#egg=openedx_learning # via # -c requirements/constraints.txt # -r requirements/edx/doc.txt diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index f323574a0376..b4ed9843329c 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -1013,7 +1013,7 @@ openedx-filters==2.1.0 # ora2 openedx-forum==0.4.0 # via -r requirements/edx/base.txt -openedx-learning==git+https://github.com/ormsbee/openedx-learning.git@big-authoring +git+https://github.com/ormsbee/openedx-learning.git@big-authoring#egg=openedx_learning # via # -c requirements/constraints.txt # -r requirements/edx/base.txt diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index a6fccf0a251e..b17bb26aecae 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -1063,7 +1063,7 @@ openedx-filters==2.1.0 # ora2 openedx-forum==0.4.0 # via -r requirements/edx/base.txt -openedx-learning==git+https://github.com/ormsbee/openedx-learning.git@big-authoring +git+https://github.com/ormsbee/openedx-learning.git@big-authoring#egg=openedx_learning # via # -c requirements/constraints.txt # -r requirements/edx/base.txt From bf5d906559be0a7b4bc986545b3704022aa0273f Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Fri, 30 Jan 2026 12:42:38 -0500 Subject: [PATCH 11/11] temp: introduce squashed migrations --- ...r_componentlink_upstream_block_and_more.py | 183 ++++++++++++++++++ ...r_componentlink_upstream_block_and_more.py | 26 +-- ...ockmigration_change_log_record_and_more.py | 146 ++++++++++++++ ...ockmigration_change_log_record_and_more.py | 56 +++--- lms/envs/common.py | 8 +- ...2_alter_contentlibrary_learning_package.py | 99 ++++++++++ ...2_alter_contentlibrary_learning_package.py | 16 +- 7 files changed, 472 insertions(+), 62 deletions(-) create mode 100644 cms/djangoapps/contentstore/migrations/0001_squashed_0015_alter_componentlink_upstream_block_and_more.py create mode 100644 cms/djangoapps/modulestore_migrator/migrations/0001_squashed_0007_alter_modulestoreblockmigration_change_log_record_and_more.py create mode 100644 openedx/core/djangoapps/content_libraries/migrations/0001_squashed_0012_alter_contentlibrary_learning_package.py diff --git a/cms/djangoapps/contentstore/migrations/0001_squashed_0015_alter_componentlink_upstream_block_and_more.py b/cms/djangoapps/contentstore/migrations/0001_squashed_0015_alter_componentlink_upstream_block_and_more.py new file mode 100644 index 000000000000..7385e9b0ddd8 --- /dev/null +++ b/cms/djangoapps/contentstore/migrations/0001_squashed_0015_alter_componentlink_upstream_block_and_more.py @@ -0,0 +1,183 @@ +# Generated by Django 5.2.10 on 2026-01-30 01:23 + +import django.db.migrations.operations.special +import django.db.models.deletion +import opaque_keys.edx.django.models +import openedx_learning.lib.fields +import openedx_learning.lib.validators +import uuid +from django.conf import settings +from django.db import migrations, models + +from cms.djangoapps.contentstore.config.waffle import ENABLE_CHECKLISTS_QUALITY +from cms.djangoapps.contentstore.toggles import ENABLE_REACT_MARKDOWN_EDITOR + + +def create_checklists_quality_waffle_flag(apps, schema_editor): + Flag = apps.get_model('waffle', 'Flag') + # Replacement for flag_undefined_default=True on flag definition + Flag.objects.get_or_create(name=ENABLE_CHECKLISTS_QUALITY.name, defaults={'everyone': True}) + + +def create_markdown_editor_waffle_flag(apps, schema_editor): + Flag = apps.get_model('waffle', 'Flag') + Flag.objects.get_or_create( + name=ENABLE_REACT_MARKDOWN_EDITOR.name, defaults={'everyone': True} + ) + + +class Migration(migrations.Migration): + + replaces = [('contentstore', '0001_initial'), ('contentstore', '0002_add_assets_page_flag'), ('contentstore', '0003_remove_assets_page_flag'), ('contentstore', '0004_remove_push_notification_configmodel_table'), ('contentstore', '0005_add_enable_checklists_quality_waffle_flag'), ('contentstore', '0006_courseoutlineregenerate'), ('contentstore', '0007_backfillcoursetabsconfig'), ('contentstore', '0008_cleanstalecertificateavailabilitydatesconfig'), ('contentstore', '0009_learningcontextlinksstatus_publishableentitylink'), ('contentstore', '0010_container_link_models'), ('contentstore', '0011_enable_markdown_editor_flag_by_default'), ('contentstore', '0012_componentlink_top_level_parent_and_more'), ('contentstore', '0013_componentlink_downstream_is_modified_and_more'), ('contentstore', '0014_remove_componentlink_downstream_is_modified_and_more'), ('contentstore', '0015_alter_componentlink_upstream_block_and_more')] + + initial = True + + dependencies = [ + ('course_overviews', '0024_overview_adds_has_highlights'), + ('oel_components', '0003_remove_componentversioncontent_learner_downloadable'), + ('oel_publishing', '0002_alter_learningpackage_key_and_more'), + ('oel_publishing', '0003_containers'), + ('openedx_content', '0002_rename_tables_to_openedx_content'), + ('waffle', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='VideoUploadConfig', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('profile_whitelist', models.TextField(blank=True, help_text='A comma-separated list of names of profiles to include in video encoding downloads.')), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ], + options={ + 'ordering': ('-change_date',), + 'abstract': False, + }, + ), + migrations.RunPython( + code=create_checklists_quality_waffle_flag, + reverse_code=django.db.migrations.operations.special.RunPython.noop, + ), + migrations.CreateModel( + name='CourseOutlineRegenerate', + fields=[ + ], + options={ + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('course_overviews.courseoverview',), + ), + migrations.CreateModel( + name='BackfillCourseTabsConfig', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('start_index', models.IntegerField(default=0, help_text='Index of first course to start backfilling (in an alphabetically sorted list of courses)')), + ('count', models.IntegerField(default=0, help_text='How many courses to backfill in this run (or zero for all courses)')), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ], + options={ + 'verbose_name': 'Arguments for backfill_course_tabs', + 'verbose_name_plural': 'Arguments for backfill_course_tabs', + }, + ), + migrations.CreateModel( + name='CleanStaleCertificateAvailabilityDatesConfig', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('arguments', models.TextField(blank=True, help_text="A space seperated collection of arguments to be used when running the `clean_stale_certificate_available_dates` management command.' See the management command for options.")), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ], + options={ + 'verbose_name': "Arguments for 'clean_stale_certificate_availability_dates'", + 'verbose_name_plural': "Arguments for 'clean_stale_certificate_availability_dates'", + }, + ), + migrations.CreateModel( + name='LearningContextLinksStatus', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('context_key', opaque_keys.edx.django.models.CourseKeyField(help_text='Linking status for course context key', max_length=255, unique=True)), + ('status', models.CharField(choices=[('pending', 'Pending'), ('processing', 'Processing'), ('failed', 'Failed'), ('completed', 'Completed')], help_text='Status of links in given learning context/course.', max_length=20)), + ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ('updated', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ], + options={ + 'verbose_name': 'Learning Context Links status', + 'verbose_name_plural': 'Learning Context Links status', + }, + ), + migrations.CreateModel( + name='ComponentLink', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), + ('upstream_usage_key', opaque_keys.edx.django.models.UsageKeyField(help_text='Upstream block usage key, this value cannot be null and useful to track upstream library blocks that do not exist yet', max_length=255)), + ('upstream_context_key', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, db_index=True, help_text='Upstream context key i.e., learning_package/library key', max_length=500)), + ('downstream_usage_key', opaque_keys.edx.django.models.UsageKeyField(max_length=255, unique=True)), + ('downstream_context_key', opaque_keys.edx.django.models.CourseKeyField(db_index=True, max_length=255)), + ('version_synced', models.IntegerField()), + ('version_declined', models.IntegerField(blank=True, null=True)), + ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ('updated', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ('upstream_block', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='openedx_content.component')), + ], + options={ + 'verbose_name': 'Component Link', + 'verbose_name_plural': 'Component Links', + }, + ), + migrations.CreateModel( + name='ContainerLink', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), + ('upstream_context_key', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, db_index=True, help_text='Upstream context key i.e., learning_package/library key', max_length=500)), + ('downstream_usage_key', opaque_keys.edx.django.models.UsageKeyField(max_length=255, unique=True)), + ('downstream_context_key', opaque_keys.edx.django.models.CourseKeyField(db_index=True, max_length=255)), + ('version_synced', models.IntegerField()), + ('version_declined', models.IntegerField(blank=True, null=True)), + ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ('updated', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ('upstream_container_key', opaque_keys.edx.django.models.ContainerKeyField(help_text='Upstream block key (e.g. lct:...), this value cannot be null and is useful to track upstream library blocks that do not exist yet or were deleted.', max_length=255)), + ('upstream_container', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='openedx_content.container')), + ], + options={ + 'abstract': False, + 'verbose_name': 'Container Link', + 'verbose_name_plural': 'Container Links', + }, + ), + migrations.RunPython( + code=create_markdown_editor_waffle_flag, + reverse_code=django.db.migrations.operations.special.RunPython.noop, + ), + migrations.AddField( + model_name='componentlink', + name='top_level_parent', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='contentstore.containerlink'), + ), + migrations.AddField( + model_name='containerlink', + name='top_level_parent', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='contentstore.containerlink'), + ), + migrations.AddField( + model_name='componentlink', + name='downstream_customized', + field=models.JSONField(default=list, help_text='Names of the fields which have values set on the upstream block yet have been explicitly overridden on this downstream block'), + ), + migrations.AddField( + model_name='containerlink', + name='downstream_customized', + field=models.JSONField(default=list, help_text='Names of the fields which have values set on the upstream block yet have been explicitly overridden on this downstream block'), + ), + ] diff --git a/cms/djangoapps/contentstore/migrations/0015_alter_componentlink_upstream_block_and_more.py b/cms/djangoapps/contentstore/migrations/0015_alter_componentlink_upstream_block_and_more.py index b57da0da34f1..c5fab7274812 100644 --- a/cms/djangoapps/contentstore/migrations/0015_alter_componentlink_upstream_block_and_more.py +++ b/cms/djangoapps/contentstore/migrations/0015_alter_componentlink_upstream_block_and_more.py @@ -2,30 +2,24 @@ import django.db.models.deletion from django.db import migrations, models -from django.db.migrations.operations.special import SeparateDatabaseAndState class Migration(migrations.Migration): dependencies = [ ('contentstore', '0014_remove_componentlink_downstream_is_modified_and_more'), - ('openedx_content', '0001_initial'), + ('openedx_content', '0002_rename_tables_to_openedx_content'), ] operations = [ - SeparateDatabaseAndState( - database_operations=[], - state_operations=[ - migrations.AlterField( - model_name='componentlink', - name='upstream_block', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='openedx_content.component'), - ), - migrations.AlterField( - model_name='containerlink', - name='upstream_container', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='openedx_content.container'), - ), - ] + migrations.AlterField( + model_name='componentlink', + name='upstream_block', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='openedx_content.component'), + ), + migrations.AlterField( + model_name='containerlink', + name='upstream_container', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='links', to='openedx_content.container'), ), ] diff --git a/cms/djangoapps/modulestore_migrator/migrations/0001_squashed_0007_alter_modulestoreblockmigration_change_log_record_and_more.py b/cms/djangoapps/modulestore_migrator/migrations/0001_squashed_0007_alter_modulestoreblockmigration_change_log_record_and_more.py new file mode 100644 index 000000000000..361d4afaf513 --- /dev/null +++ b/cms/djangoapps/modulestore_migrator/migrations/0001_squashed_0007_alter_modulestoreblockmigration_change_log_record_and_more.py @@ -0,0 +1,146 @@ +# Generated by Django 5.2.10 on 2026-01-30 01:29 + +import django.db.models.deletion +import django.utils.timezone +import model_utils.fields +import opaque_keys.edx.django.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [('modulestore_migrator', '0001_initial'), ('modulestore_migrator', '0002_alter_modulestoremigration_task_status'), ('modulestore_migrator', '0003_modulestoremigration_is_failed'), ('modulestore_migrator', '0004_alter_modulestoreblockmigration_target_squashed_0005_modulestoreblockmigration_unsupported_reason'), ('modulestore_migrator', '0006_alter_modulestoreblocksource_forwarded_and_more'), ('modulestore_migrator', '0007_alter_modulestoreblockmigration_change_log_record_and_more')] + + initial = True + + dependencies = [ + ('content_staging', '0006_alter_userclipboard_source_usage_key'), + ('oel_collections', '0005_alter_collection_options_alter_collection_enabled'), + ('oel_publishing', '0008_alter_draftchangelogrecord_options_and_more'), + ('openedx_content', '0002_rename_tables_to_openedx_content'), + ('user_tasks', '0004_url_textfield'), + ] + + operations = [ + migrations.CreateModel( + name='ModulestoreBlockMigration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), + ('change_log_record', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='openedx_content.draftchangelogrecord')), + ], + ), + migrations.CreateModel( + name='ModulestoreMigration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('source_version', models.CharField(blank=True, help_text='Migrated content version, the hash of published content version', max_length=255, null=True)), + ('composition_level', models.CharField(choices=[('component', 'Component'), ('unit', 'Unit'), ('subsection', 'Subsection'), ('section', 'Section')], default='component', help_text='Maximum hierachy level at which content should be aggregated in target library', max_length=255)), + ('repeat_handling_strategy', models.CharField(choices=[('skip', 'Skip'), ('fork', 'Fork'), ('update', 'Update')], default='skip', help_text='If a piece of content already exists in the content library, choose how to handle it.', max_length=24)), + ('preserve_url_slugs', models.BooleanField(default=False, help_text='Should the migration preserve the location IDs of the existing blocks?If not, then new, unique human-readable IDs will be generated based on the block titles.')), + ('change_log', models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='openedx_content.draftchangelog')), + ], + ), + migrations.CreateModel( + name='ModulestoreSource', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', opaque_keys.edx.django.models.LearningContextKeyField(help_text='Key of the content source (a course or a legacy library)', max_length=255, unique=True)), + ('forwarded', models.OneToOneField(blank=True, help_text='If set, the system will forward references of this source over to the target of this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='forwards', to='modulestore_migrator.modulestoremigration')), + ], + ), + migrations.AddField( + model_name='modulestoremigration', + name='source', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='migrations', to='modulestore_migrator.modulestoresource'), + ), + migrations.AddField( + model_name='modulestoremigration', + name='staged_content', + field=models.OneToOneField(help_text='Modulestore content is processed and staged before importing it to a learning packge. We temporarily save the staged content to allow for troubleshooting of failed migrations.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='content_staging.stagedcontent'), + ), + migrations.AddField( + model_name='modulestoremigration', + name='target', + field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='openedx_content.learningpackage'), + ), + migrations.AddField( + model_name='modulestoremigration', + name='target_collection', + field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='openedx_content.collection'), + ), + migrations.AddField( + model_name='modulestoremigration', + name='task_status', + field=models.ForeignKey(help_text='Tracks the status of the task which is executing this migration. In a bulk migration, the same task can be multiple migrations', on_delete=django.db.models.deletion.RESTRICT, related_name='migrations', to='user_tasks.usertaskstatus'), + ), + migrations.CreateModel( + name='ModulestoreBlockSource', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), + ('key', opaque_keys.edx.django.models.UsageKeyField(help_text='Original usage key of the XBlock that has been imported.', max_length=255)), + ('forwarded', models.OneToOneField(help_text='If set, the system will forward references of this block source over to the target of this block migration', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='forwards', to='modulestore_migrator.modulestoreblockmigration')), + ('overall_source', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='blocks', to='modulestore_migrator.modulestoresource')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='modulestoreblockmigration', + name='overall_migration', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='block_migrations', to='modulestore_migrator.modulestoremigration'), + ), + migrations.AddField( + model_name='modulestoreblockmigration', + name='source', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='modulestore_migrator.modulestoreblocksource'), + ), + migrations.AddField( + model_name='modulestoreblockmigration', + name='target', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='openedx_content.publishableentity'), + ), + migrations.AlterUniqueTogether( + name='modulestoreblockmigration', + unique_together={('overall_migration', 'source'), ('overall_migration', 'target')}, + ), + migrations.AddField( + model_name='modulestoremigration', + name='is_failed', + field=models.BooleanField(default=False, help_text='is the migration failed?'), + ), + migrations.AlterField( + model_name='modulestoreblockmigration', + name='target', + field=models.ForeignKey(blank=True, help_text='The target entity of this block migration, set to null if it fails to migrate', null=True, on_delete=django.db.models.deletion.CASCADE, to='openedx_content.publishableentity'), + ), + migrations.AddField( + model_name='modulestoreblockmigration', + name='unsupported_reason', + field=models.TextField(blank=True, help_text='Reason if the block is unsupported and target is set to null', null=True), + ), + migrations.AlterField( + model_name='modulestoreblocksource', + name='forwarded', + field=models.OneToOneField(help_text='If set, the system will forward references of this block source over to the target of this block migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='modulestore_migrator.modulestoreblockmigration'), + ), + migrations.AlterField( + model_name='modulestoreblocksource', + name='key', + field=opaque_keys.edx.django.models.UsageKeyField(help_text='Original usage key of the XBlock that has been imported.', max_length=255, unique=True), + ), + migrations.AlterField( + model_name='modulestoresource', + name='forwarded', + field=models.OneToOneField(blank=True, help_text='If set, the system will forward references of this source over to the target of this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='modulestore_migrator.modulestoremigration'), + ), + migrations.AlterField( + model_name='modulestoremigration', + name='change_log', + field=models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='openedx_content.draftchangelog'), + ), + ] diff --git a/cms/djangoapps/modulestore_migrator/migrations/0007_alter_modulestoreblockmigration_change_log_record_and_more.py b/cms/djangoapps/modulestore_migrator/migrations/0007_alter_modulestoreblockmigration_change_log_record_and_more.py index c5b504b6ae67..11d66b4a89ff 100644 --- a/cms/djangoapps/modulestore_migrator/migrations/0007_alter_modulestoreblockmigration_change_log_record_and_more.py +++ b/cms/djangoapps/modulestore_migrator/migrations/0007_alter_modulestoreblockmigration_change_log_record_and_more.py @@ -2,45 +2,39 @@ import django.db.models.deletion from django.db import migrations, models -from django.db.migrations.operations.special import SeparateDatabaseAndState class Migration(migrations.Migration): dependencies = [ ('modulestore_migrator', '0006_alter_modulestoreblocksource_forwarded_and_more'), - ('openedx_content', '0001_initial'), + ('openedx_content', '0002_rename_tables_to_openedx_content'), ] operations = [ - SeparateDatabaseAndState( - database_operations=[], - state_operations=[ - migrations.AlterField( - model_name='modulestoreblockmigration', - name='change_log_record', - field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='openedx_content.draftchangelogrecord'), - ), - migrations.AlterField( - model_name='modulestoreblockmigration', - name='target', - field=models.ForeignKey(blank=True, help_text='The target entity of this block migration, set to null if it fails to migrate', null=True, on_delete=django.db.models.deletion.CASCADE, to='openedx_content.publishableentity'), - ), - migrations.AlterField( - model_name='modulestoremigration', - name='change_log', - field=models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='openedx_content.draftchangelog'), - ), - migrations.AlterField( - model_name='modulestoremigration', - name='target', - field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='openedx_content.learningpackage'), - ), - migrations.AlterField( - model_name='modulestoremigration', - name='target_collection', - field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='openedx_content.collection'), - ), - ] + migrations.AlterField( + model_name='modulestoreblockmigration', + name='change_log_record', + field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='openedx_content.draftchangelogrecord'), + ), + migrations.AlterField( + model_name='modulestoreblockmigration', + name='target', + field=models.ForeignKey(blank=True, help_text='The target entity of this block migration, set to null if it fails to migrate', null=True, on_delete=django.db.models.deletion.CASCADE, to='openedx_content.publishableentity'), + ), + migrations.AlterField( + model_name='modulestoremigration', + name='change_log', + field=models.ForeignKey(help_text='Changelog entry in the target learning package which records this migration', null=True, on_delete=django.db.models.deletion.SET_NULL, to='openedx_content.draftchangelog'), + ), + migrations.AlterField( + model_name='modulestoremigration', + name='target', + field=models.ForeignKey(help_text='Content will be imported into this library', on_delete=django.db.models.deletion.CASCADE, to='openedx_content.learningpackage'), + ), + migrations.AlterField( + model_name='modulestoremigration', + name='target_collection', + field=models.ForeignKey(blank=True, help_text='Optional - Collection (within the target library) into which imported content will be grouped', null=True, on_delete=django.db.models.deletion.SET_NULL, to='openedx_content.collection'), ), ] diff --git a/lms/envs/common.py b/lms/envs/common.py index 935bfb6d973e..c1a9dc9689f4 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -2025,10 +2025,10 @@ # not here and LMS migrations are run before CMS migrations, it will cause # errors (certain openedx_learning apps ) *openedx_learning_apps_to_install(), - 'cms.djangoapps.contentstore', - 'cms.djangoapps.modulestore_migrator', - 'openedx.core.djangoapps.content.search', - 'openedx.core.djangoapps.content_staging', +# 'cms.djangoapps.contentstore', +# 'cms.djangoapps.modulestore_migrator', +# 'openedx.core.djangoapps.content.search', +# 'openedx.core.djangoapps.content_staging', ] # Add LMS specific optional apps diff --git a/openedx/core/djangoapps/content_libraries/migrations/0001_squashed_0012_alter_contentlibrary_learning_package.py b/openedx/core/djangoapps/content_libraries/migrations/0001_squashed_0012_alter_contentlibrary_learning_package.py new file mode 100644 index 000000000000..61c3d2b77dbc --- /dev/null +++ b/openedx/core/djangoapps/content_libraries/migrations/0001_squashed_0012_alter_contentlibrary_learning_package.py @@ -0,0 +1,99 @@ +# Generated by Django 5.2.10 on 2026-01-30 01:20 + +import django.db.models.deletion +import opaque_keys.edx.django.models +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [('content_libraries', '0001_initial'), ('content_libraries', '0002_group_permissions'), ('content_libraries', '0003_contentlibrary_type'), ('content_libraries', '0004_contentlibrary_license'), ('content_libraries', '0005_ltigradedresource_ltiprofile'), ('content_libraries', '0006_auto_20210615_1916'), ('content_libraries', '0005_contentlibraryblockimporttask'), ('content_libraries', '0007_merge_20210818_0614'), ('content_libraries', '0008_auto_20210818_2148'), ('content_libraries', '0009_alter_contentlibrary_authorized_lti_configs'), ('content_libraries', '0010_contentlibrary_learning_package_and_more'), ('content_libraries', '0011_remove_contentlibrary_bundle_uuid_and_more'), ('content_libraries', '0012_alter_contentlibrary_learning_package')] + + initial = True + + dependencies = [ + ('auth', '0008_alter_user_username_max_length'), + ('lti1p3_tool_config', '0001_initial'), + ('oel_publishing', '0001_initial'), + ('openedx_content', '0002_rename_tables_to_openedx_content'), + ('organizations', '0007_historicalorganization'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='ContentLibrary', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('slug', models.SlugField(allow_unicode=True)), + ('allow_public_learning', models.BooleanField(default=False, help_text='\n Allow any user (even unregistered users) to view and interact with\n content in this library (in the LMS; not in Studio). If this is not\n enabled, then the content in this library is not directly accessible\n in the LMS, and learners will only ever see this content if it is\n explicitly added to a course. If in doubt, leave this unchecked.\n ')), + ('allow_public_read', models.BooleanField(default=False, help_text="\n Allow any user with Studio access to view this library's content in\n Studio, use it in their courses, and copy content out of this\n library. If in doubt, leave this unchecked.\n ")), + ('org', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='organizations.organization')), + ('license', models.CharField(choices=[('', 'All Rights Reserved.'), ('CC:4.0:BY', 'Creative Commons Attribution 4.0'), ('CC:4.0:BY:NC', 'Creative Commons Attribution-NonCommercial 4.0'), ('CC:4.0:BY:NC:ND', 'Creative Commons Attribution-NonCommercial-NoDerivatives 4.0'), ('CC:4.0:BY:NC:SA', 'Creative Commons Attribution-NonCommercial-ShareAlike 4.0'), ('CC:4.0:BY:ND', 'Creative Commons Attribution-NoDerivatives 4.0'), ('CC:4.0:BY:SA', 'Creative Commons Attribution-ShareAlike 4.0')], default='', max_length=25)), + ('authorized_lti_configs', models.ManyToManyField(blank=True, help_text="List of authorized LTI tool configurations that can access this library's content through LTI launches, if empty no LTI launch is allowed.", related_name='content_libraries', to='lti1p3_tool_config.ltitool')), + ('learning_package', models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='openedx_content.learningpackage')), + ], + options={ + 'verbose_name_plural': 'Content Libraries', + 'unique_together': {('org', 'slug')}, + }, + ), + migrations.CreateModel( + name='ContentLibraryPermission', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('access_level', models.CharField(choices=[('admin', 'Administer users and author content'), ('author', 'Author content'), ('read', 'Read-only')], max_length=30)), + ('library', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='permission_grants', to='content_libraries.contentlibrary')), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='auth.group')), + ], + options={ + 'ordering': ('user__username', 'group__name'), + 'unique_together': {('library', 'group'), ('library', 'user')}, + }, + ), + migrations.CreateModel( + name='LtiProfile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('platform_id', models.CharField(help_text='The LTI platform identifier to which this profile belongs to.', max_length=255, verbose_name='lti platform identifier')), + ('client_id', models.CharField(help_text='The LTI client identifier generated by the LTI platform.', max_length=255, verbose_name='client identifier')), + ('subject_id', models.CharField(help_text='Identifies the entity that initiated the launch request, commonly a user.', max_length=255, verbose_name='subject identifier')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('user', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='contentlibraries_lti_profile', to=settings.AUTH_USER_MODEL, verbose_name='open edx user')), + ], + options={ + 'unique_together': {('platform_id', 'client_id', 'subject_id')}, + }, + ), + migrations.CreateModel( + name='ContentLibraryBlockImportTask', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('state', models.CharField(choices=[('created', 'Task was created, but not queued to run.'), ('pending', 'Task was created and queued to run.'), ('running', 'Task is running.'), ('failed', 'Task finished, but some blocks failed to import.'), ('successful', 'Task finished successfully.')], default='created', help_text='The state of the block import task.', max_length=30, verbose_name='state')), + ('progress', models.FloatField(default=0.0, help_text='A float from 0.0 to 1.0 representing the task progress.', verbose_name='progress')), + ('course_id', opaque_keys.edx.django.models.CourseKeyField(db_index=True, help_text='ID of the imported course.', max_length=255, verbose_name='course ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('library', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='import_tasks', to='content_libraries.contentlibrary')), + ], + options={ + 'ordering': ['-created_at', '-updated_at'], + }, + ), + migrations.CreateModel( + name='LtiGradedResource', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('usage_key', opaque_keys.edx.django.models.UsageKeyField(help_text='The usage key string of the resource serving the content of this launch.', max_length=255)), + ('resource_id', models.CharField(help_text='The LTI platform unique identifier of this resource, also known as the "resource link id".', max_length=255)), + ('resource_title', models.CharField(help_text='The LTI platform descriptive title for this resource.', max_length=255, null=True)), + ('ags_lineitem', models.CharField(help_text='If AGS was enabled during launch, this should hold the lineitem ID.', max_length=255)), + ('profile', models.ForeignKey(help_text='The authorized LTI profile that launched the resource (identifies the user).', on_delete=django.db.models.deletion.CASCADE, related_name='lti_resources', to='content_libraries.ltiprofile')), + ], + options={ + 'unique_together': {('usage_key', 'profile')}, + }, + ), + ] diff --git a/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py b/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py index 774875597bc1..1ec8fb4a78eb 100644 --- a/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py +++ b/openedx/core/djangoapps/content_libraries/migrations/0012_alter_contentlibrary_learning_package.py @@ -2,25 +2,19 @@ import django.db.models.deletion from django.db import migrations, models -from django.db.migrations.operations.special import SeparateDatabaseAndState class Migration(migrations.Migration): dependencies = [ ('content_libraries', '0011_remove_contentlibrary_bundle_uuid_and_more'), - ('openedx_content', '0001_initial'), + ('openedx_content', '0002_rename_tables_to_openedx_content'), ] operations = [ - SeparateDatabaseAndState( - database_operations=[], - state_operations=[ - migrations.AlterField( - model_name='contentlibrary', - name='learning_package', - field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='openedx_content.learningpackage'), - ), - ] + migrations.AlterField( + model_name='contentlibrary', + name='learning_package', + field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='openedx_content.learningpackage'), ), ]