refactor: switch to use openedx_content app (#37924)
The openedx-learning repo was recently refactored to consolidate its authoring apps into a single openedx_content app: https://github.com/openedx/openedx-platform/pull/37924 This commit makes the following changes to accommodate this: - Bumps the openedx-learning version to 0.31.0 to get the changes. - Creates new migrations in content_libraries, contentstore, and modulestore_migrator to foreign key references to authoring apps to point to the new openedx_content app. This is done without actually making database changes, since the openedx_content app models are taking over the existing tables that the authoring apps once pointed to. - Creates new squashed migrations in these apps that create these foreign keys to reference openedx_content app models from the start. The full rationale for how and why this was done is in the following openedx-learning ADR: https://github.com/openedx/openedx-learning/blob/main/docs/decisions/0020-merge-authoring-apps-into-openedx-content.rst These migrations should run fine from either a from-scratch scenario (i.e. a new install or CI), or when upgrading from an Ulmo-or-later database state. If you have a database state that comes from the middle of the Ulmo development cycle (e.g. October 2025), you may encounter migration errors in content_libraries, contentstore, or modulestore_migrator, with an error message complaining about missing tables. If you receive this message, run the following command: python manage.py lms migrate openedx_content 0001 Then try to run the migrations for the app that failed. Repeat if necessary for multiple apps.
This commit is contained in:
@@ -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_switch_to_openedx_content')]
|
||||
|
||||
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'),
|
||||
),
|
||||
]
|
||||
@@ -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'),
|
||||
('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'),
|
||||
),
|
||||
]
|
||||
),
|
||||
]
|
||||
@@ -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_switch_to_openedx_content')]
|
||||
|
||||
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'),
|
||||
),
|
||||
]
|
||||
@@ -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'),
|
||||
('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'),
|
||||
),
|
||||
]
|
||||
),
|
||||
]
|
||||
@@ -45,6 +45,7 @@ from corsheaders.defaults import default_headers as corsheaders_default_headers
|
||||
from datetime import timedelta
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from openedx_learning.api.django import openedx_learning_apps_to_install
|
||||
|
||||
from openedx.envs.common import * # pylint: disable=wildcard-import
|
||||
|
||||
@@ -897,14 +898,7 @@ INSTALLED_APPS = [
|
||||
|
||||
'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",
|
||||
*openedx_learning_apps_to_install(),
|
||||
]
|
||||
|
||||
### Apps only installed in some instances
|
||||
|
||||
Reference in New Issue
Block a user