Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • Getting a reference to an XBlock or XModule with the intention of rendering its views and invoking its handlers.
  • Reading or writing course static assets, such as images or other file uploads. This is done via the contentstore interface.
  • Changes to the import/export process.
  • Adding a new type of Course (e.g. Content Libraries, CCX).

Hello ModuleStore!

Code Block
languagepy
from xmodule.modulestore.django import modulestore
from opaque_keys.edx.keys import CourseKey, UsageKey
from opaque_keys import InvalidKeyError

# Old style IDs -- note the lack of Course Run info in usage_id
# course_id = "edX/DemoX.1/2014"
# usage_id = "i4x://edX/DemoX.1/problem/466f474fa4d045a8b7bde1b911e095ca"

# New style IDs -- usage_id has full Course Run info
course_id = "course-v1:edX+DemoX+Demo_Course"
usage_id = "block-v1:edX+DemoX+Demo_Course+type@problem+block@d2e35c1d294b4ba0b3b1048615605d2a"

# Parse the Course ID.
try:
    # This will return a SlashSeparatedCourseKey (old) or CourseLocator (new)
    # Always use CourseKey.from_string() when parsing Course IDs.
    course_key = CourseKey.from_string(course_id)
except InvalidKeyError:
    # Do some error handling here -- this is just completely made up
    raise ValueError("Could not parse course_id {}".format(course_id))

# Parse the Usage ID
try:
    # This will return a Location (old) or BlockUsageLocator (new)
    # Always use UsageKey.from_string() when parsing Usage IDs.
    unmapped_usage_key = UsageKey.from_string(usage_id)

    # The map_into_course() call is not necessary for BlockUsageLocators, but
    # we do it to maintain compatibility with old style usage keys.
    usage_key = unmapped_usage_key.map_into_course(course_key)
except InvalidKeyError:
    # Do some error handling here -- this is just completely made up
    raise ValueError("Could not parse usage_id {}".format(usage_id))


ms = modulestore()

# Get a single CapaDescriptor (a Capa problem, like multiple choice).
# This object has all its XModule content fields, but not the user ones.
problem = ms.get_item(usage_key)

# Query the Modulestore for all sequentials in the Course.
sequences = ms.get_items(course_key, qualifiers={'category': 'sequential'})

# Get the root CourseDescriptor
course = ms.get_course(course_key)

# List of child usage keys (Locations/BlockUsageLocators) for the chapters.
course.children

# Iterate through the descriptors for those children instead:
for chapter in course.get_children():
    print chapter.location, chapter.display_name


Why Do People Fear It?

The XBlock runtime is conceptually pretty straightforward. An XBlock is instantiated. It has handlers, views, fields, and access to certain runtime services (field data is actually one of those services). However, a number of things have contributed to complexity in this system.

...