def create_bundle_link(library_key, link_id, target_opaque_key, version=None): """ Create a new link to the resource with the specified opaque key. For now, only LibraryLocatorV2 opaque keys are supported. """ ref = ContentLibrary.objects.get_by_key(library_key) # Make sure this link ID/name is not already in use: links = blockstore_cache.get_bundle_draft_direct_links_cached( ref.bundle_uuid, DRAFT_NAME) if link_id in links: raise InvalidNameError("That link ID is already in use.") # Determine the target: if not isinstance(target_opaque_key, LibraryLocatorV2): raise TypeError( "For now, only LibraryLocatorV2 opaque keys are supported by create_bundle_link" ) target_bundle_uuid = ContentLibrary.objects.get_by_key( target_opaque_key).bundle_uuid if version is None: version = get_bundle(target_bundle_uuid).latest_version # Create the new link: draft = get_or_create_bundle_draft(ref.bundle_uuid, DRAFT_NAME) set_draft_link(draft.uuid, link_id, target_bundle_uuid, version) # Clear the cache: LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME).cache.clear() CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=library_key)
def get_bundle_links(library_key): """ Get the list of bundles/libraries linked to this content library. Returns LibraryBundleLink objects (defined above). Because every content library is a blockstore bundle, it can have "links" to other bundles, which may or may not be content libraries. This allows using XBlocks (or perhaps even static assets etc.) from another bundle without needing to duplicate/copy the data. Links always point to a specific published version of the target bundle. Links are identified by a slug-like ID, e.g. "link1" """ ref = ContentLibrary.objects.get_by_key(library_key) links = blockstore_cache.get_bundle_draft_direct_links_cached( ref.bundle_uuid, DRAFT_NAME) results = [] # To be able to quickly get the library ID from the bundle ID for links which point to other libraries, build a map: bundle_uuids = set(link_data.bundle_uuid for link_data in links.values()) libraries_linked = { lib.bundle_uuid: lib for lib in ContentLibrary.objects.select_related('org').filter( bundle_uuid__in=bundle_uuids) } for link_name, link_data in links.items(): # Is this linked bundle a content library? try: opaque_key = libraries_linked[link_data.bundle_uuid].library_key except KeyError: opaque_key = None # Append the link information: results.append( LibraryBundleLink( id=link_name, bundle_uuid=link_data.bundle_uuid, version=link_data.version, latest_version=blockstore_cache.get_bundle_version_number( link_data.bundle_uuid), opaque_key=opaque_key, )) return results
def update_bundle_link(library_key, link_id, version=None, delete=False): """ Update a bundle's link to point to the specified version of its target bundle. Use version=None to automatically point to the latest version. Use delete=True to delete the link. """ ref = ContentLibrary.objects.get_by_key(library_key) draft = get_or_create_bundle_draft(ref.bundle_uuid, DRAFT_NAME) if delete: set_draft_link(draft.uuid, link_id, None, None) else: links = blockstore_cache.get_bundle_draft_direct_links_cached(ref.bundle_uuid, DRAFT_NAME) try: link = links[link_id] except KeyError: raise InvalidNameError("That link does not exist.") if version is None: version = get_bundle(link.bundle_uuid).latest_version set_draft_link(draft.uuid, link_id, link.bundle_uuid, version) # Clear the cache: LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME).cache.clear()