In Learning Core, Content is raw file data with a media type. It has no filename or association to a ComponentVersion by itself. Content is joined to ComponentVersion via the ComponentVersionContent model, which is where the filename is located (as the key field).
This leads to some cumbersome code for callers, like the following for adding a new asset to a component block in edx-platform:
media_type_str, _encoding = mimetypes.guess_type(file_path)
# We use "application/octet-stream" as a generic fallback media type, per
# RFC 2046: https://datatracker.ietf.org/doc/html/rfc2046
# TODO: This probably makes sense to push down to openedx-learning?
media_type_str = media_type_str or "application/octet-stream"
now = datetime.now(tz=timezone.utc)
with transaction.atomic():
media_type = authoring_api.get_or_create_media_type(media_type_str)
content = authoring_api.get_or_create_file_content(
component.publishable_entity.learning_package.id,
media_type.id,
data=file_content,
created=now,
)
component_version = authoring_api.create_next_component_version(
component.pk,
content_to_replace={file_path: content.id},
created=now,
created_by=user.id if user else None,
)
If create_next_component_version were instead modified so that the values in content_to_replace could be either integers (the Content id) or bytes, then the above code could look like this:
with transaction.atomic():
component_version = authoring_api.create_next_component_version(
component.pk,
content_to_replace={file_path: file_content},
created=datetime.now(tz=timezone.utc),
created_by=user.id if user else None,
)
That would allow developers using openedx-learning to add, update, and delete normal assets without having to really think about the underlying data relationship between Content and ComponentVersion–doing the media type guessing and implicit Content lookup/creation would be taken care of by create_next_component_version.
Using Content IDs should still be supported, since we sometimes want fine-grained control over the media type (each XBlock type defines its own), or whether it's backed by a file system or a database field. This ticket is about implementing a small enhancement to create_next_component_version to cover the 90% use case of people wanting to add file-backed content that can rely on the file_path to guess the media type.
In Learning Core,
Contentis raw file data with a media type. It has no filename or association to aComponentVersionby itself.Contentis joined toComponentVersionvia theComponentVersionContentmodel, which is where the filename is located (as thekeyfield).This leads to some cumbersome code for callers, like the following for adding a new asset to a component block in edx-platform:
If
create_next_component_versionwere instead modified so that the values incontent_to_replacecould be either integers (the Contentid) orbytes, then the above code could look like this:That would allow developers using openedx-learning to add, update, and delete normal assets without having to really think about the underlying data relationship between
ContentandComponentVersion–doing the media type guessing and implicitContentlookup/creation would be taken care of bycreate_next_component_version.Using Content IDs should still be supported, since we sometimes want fine-grained control over the media type (each XBlock type defines its own), or whether it's backed by a file system or a database field. This ticket is about implementing a small enhancement to
create_next_component_versionto cover the 90% use case of people wanting to add file-backed content that can rely on thefile_pathto guess the media type.