Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Generated by Django 4.2.23 on 2025-08-19 16:21

from django.db import migrations


class Migration(migrations.Migration):

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

operations = [
migrations.AlterUniqueTogether(
name='publishableentityimport',
unique_together=None,
),
migrations.RemoveField(
model_name='publishableentityimport',
name='import_event',
),
migrations.RemoveField(
model_name='publishableentityimport',
name='resulting_change',
),
migrations.RemoveField(
model_name='publishableentityimport',
name='resulting_mapping',
),
migrations.AlterUniqueTogether(
name='publishableentitymapping',
unique_together=None,
),
migrations.RemoveField(
model_name='publishableentitymapping',
name='target_entity',
),
migrations.RemoveField(
model_name='publishableentitymapping',
name='target_package',
),
migrations.AlterUniqueTogether(
name='stagedcontentforimport',
unique_together=None,
),
migrations.RemoveField(
model_name='stagedcontentforimport',
name='import_event',
),
migrations.RemoveField(
model_name='stagedcontentforimport',
name='staged_content',
),
migrations.DeleteModel(
name='Import',
),
migrations.DeleteModel(
name='PublishableEntityImport',
),
migrations.DeleteModel(
name='PublishableEntityMapping',
),
migrations.DeleteModel(
name='StagedContentForImport',
),
]
138 changes: 1 addition & 137 deletions cms/djangoapps/import_from_modulestore/models.py
Original file line number Diff line number Diff line change
@@ -1,139 +1,3 @@
"""
Models for the course to library import app.
Models for the course to library import app (TO BE DELETED)
"""
import uuid as uuid_tools

from django.contrib.auth import get_user_model
from django.db import models
from django.utils.translation import gettext_lazy as _

from model_utils.models import TimeStampedModel
from opaque_keys.edx.django.models import (
LearningContextKeyField,
UsageKeyField,
)
from openedx_learning.api.authoring_models import LearningPackage, PublishableEntity

from .data import ImportStatus

User = get_user_model()


class Import(TimeStampedModel):
"""
Represents the action of a user importing a modulestore-based course or legacy
library into a learning-core based learning package (today, that is always a content library).
"""

uuid = models.UUIDField(default=uuid_tools.uuid4, editable=False, unique=True)
status = models.CharField(
max_length=100,
choices=ImportStatus.choices,
default=ImportStatus.NOT_STARTED,
db_index=True
)
user = models.ForeignKey(User, on_delete=models.CASCADE)

# Note: For now, this will always be a course key. In the future, it may be a legacy library key.
source_key = LearningContextKeyField(help_text=_('The modulestore course'), max_length=255, db_index=True)
target_change = models.ForeignKey(to='oel_publishing.DraftChangeLog', on_delete=models.SET_NULL, null=True)

class Meta:
verbose_name = _('Import from modulestore')
verbose_name_plural = _('Imports from modulestore')

def __str__(self):
return f'{self.source_key} → {self.target_change}'

def set_status(self, status: ImportStatus):
"""
Set import status.
"""
self.status = status
self.save()
if status in [ImportStatus.IMPORTED, ImportStatus.CANCELED]:
self.clean_related_staged_content()

def clean_related_staged_content(self) -> None:
"""
Clean related staged content.
"""
for staged_content_for_import in self.staged_content_for_import.all():
staged_content_for_import.staged_content.delete()


class PublishableEntityMapping(TimeStampedModel):
"""
Represents a mapping between a source usage key and a target publishable entity.
"""

source_usage_key = UsageKeyField(
max_length=255,
help_text=_('Original usage key/ID of the thing that has been imported.'),
)
target_package = models.ForeignKey(LearningPackage, on_delete=models.CASCADE)
target_entity = models.ForeignKey(PublishableEntity, on_delete=models.CASCADE)

class Meta:
unique_together = ('source_usage_key', 'target_package')

def __str__(self):
return f'{self.source_usage_key} → {self.target_entity}'


class PublishableEntityImport(TimeStampedModel):
"""
Represents a publishableentity version that has been imported into a learning package (e.g. content library)

This is a many-to-many relationship between a container version and a course to library import.
"""

import_event = models.ForeignKey(Import, on_delete=models.CASCADE)
resulting_mapping = models.ForeignKey(PublishableEntityMapping, on_delete=models.SET_NULL, null=True, blank=True)
resulting_change = models.OneToOneField(
to='oel_publishing.DraftChangeLogRecord',
# a changelog record can be pruned, which would set this to NULL, but not delete the
# entire import record
null=True,
on_delete=models.SET_NULL,
)

class Meta:
unique_together = (
('import_event', 'resulting_mapping'),
)

def __str__(self):
return f'{self.import_event} → {self.resulting_mapping}'


class StagedContentForImport(TimeStampedModel):
"""
Represents m2m relationship between an import and staged content created for that import.
"""

import_event = models.ForeignKey(
Import,
on_delete=models.CASCADE,
related_name='staged_content_for_import',
)
staged_content = models.OneToOneField(
to='content_staging.StagedContent',
on_delete=models.CASCADE,
related_name='staged_content_for_import',
)
# Since StagedContent stores all the keys of the saved blocks, this field was added to optimize search.
source_usage_key = UsageKeyField(
max_length=255,
help_text=_(
'The original Usage key of the highest-level component that was saved in StagedContent.'
),
)

class Meta:
unique_together = (
('import_event', 'staged_content'),
)

def __str__(self):
return f'{self.import_event} → {self.staged_content}'
Loading