Open edX 56 网 XBlock 视频插件开发(基础)

本文介绍如何创建一个XBlock来嵌入56网视频,包括安装XBlock-SDK、定义XBlock类及属性、实现视图和处理编辑操作等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

明确目的

  • Studio 填入url
  • lms对应章节能看到56播放器,并能播

实质,网页嵌入类似于:

<iframesrc="http://v.56.com/open_iframeplayer/3000005311_NjQzNTcxMDA.html"width="600"height="480"border="0"scrolling="no"frameborder="0"></iframe>

设置

安装XBlock-SDK

注:由于模板命名问题,Windows用户无法使用该SDK
从 git 获取源代码

创建并使用新的virtualenv

mk virtualenv xblock-sdk

安装依赖

pip  install -r requirements.txt

创建并初始化sqllite

python manage.py syncdb

运行django开发环境

python manage.py runserver 0.0.0.0:8000

浏览器访问 https://IP:8000/将会看到如下界面:


创建一个新的XBlock

最简单的方法就是通过xblock-sdk 提供的 script/startnew.py 脚本创建,期间需要提供自己的XBlock的名称和类名
以下演示将手动创建自己的XBlock

cd..
mkdir xblock-open56
cd xblock-open56/
git init
Initialized empty Git repository in/home/iflab/xblock-open56/.git/
类& 属性 (data schema)

我们想要让需要嵌入的代码中src、width、height可以被改变:

故创建一个XBlock的子类来控制标签, 命名为Open56Block,并在xblock-open56/open56.py 中定义好
embed标签将拥有三个属性src, width, 和 height(您可以更具自己的意愿添加),我们在Open56Block类中也定义下这些属性:

from xblock.core import XBlock
from xblock.fields import Scope, Integer, String

classOpen56Block(XBlock):
    """
        An XBlock providing Open56 capabilities for video
        """

        src =String(help="URL of the video page at the provider", default=None, scope=Scope.content)
        width =Integer(help="width of the video", default=800, scope=Scope.content)
        height =Integer(help="height of the video", default=450, scope=Scope.content)

我们指定这些属性的类型String/Integer,缺省值和内容类型
这里三个属性都被预定义为Scope.content(参见fields详细定义)

视图: HTML, templates & fragments

我们在Open56Block添加新的方法Open56Block.student_view(),实现播放 Open56Block.src 中定义的56视频的功能

importpkg_resources

    fromxblock.core importXBlock
    fromxblock.fields importScope, Integer, String
    fromxblock.fragment importFragment

    classOpen56Block(XBlock):
        [...]

        defstudent_view(self, context=None):
            """
            The primary view of the Open56Block, shown to students
            when viewing courses.
            """
            # Load the HTML fragment from within the package and fill in the template
            html_str =pkg_resources.resource_string(__name__, "static/html/open56_view.html")
            frag =Fragment(unicode(html_str).format(src=self.src, width=self.width, height=self.height))
            returnfrag

用户输入的src地址以及视频框长宽,将会插入到模板文件xblock-open56/static/html/open56_view.html中.输出Fragment,返回给包含页面.

静态文件

我们使用Python pkg_resources module来载入静态资源,开发者可以自由配置自己的 css, html, 和js 目录结构,只要pkg_resources能够正确加载。
我们在xblock-open56/static/html/open56_view.html创建一个简单的模板文件:

<divclass="open56_block">
    <iframesrc="{src}"width="{width}"height="{height}"border="0"scrolling="no"frameborder="0"></iframe>
</div>

完成这一步,读者应该熟悉 pkg_resources 模块的加载流程,稍后我们将用此模块加载CSS和JS

从workbench加载一个示例

我们之前定义的标签是不是真的生效了?让我们来试想我们正在建立一门新的课程,想要对学生播放来自http://v.56.com/open_iframeplayer/3000005311_NjQzNTcxMDA.html的视频,可以使用如下方法来标记

    <vertical_demo>
        <html_demo><div>Rate the video:</div></html_demo>
        <thumbs/>
    </vertical_demo>

这样,一门新的视频课程OK-这样的标记构成了课程内容的基本静态结构块,讲师集合了类似于这样的不同功能的XBlock,最终得到一个完全用XBlock描述的课程文档树
在这里我们展示三个元素,用 XBlock标记。首先是我没的视频, 使用 标签, 然后是 HTML

标签, 再然后 XBlock, 允许学生点击 thumbs (up/down)来评定视频质量
需要指出的是不加修饰的上述文本是独立于XBlock的——XBlocks的实例化、块/视图 调用方法是由runtime执行。然而,workbench提供了一种快速的方法在一个scenario中加载一组“用法”(XBlocks的单个实例)。在 Open56Blcok 类中为workbench定义一个scenario方法:
@staticmethod
    defworkbench_scenarios():
        """A canned scenario for display in the workbench."""
        return[
            ("Open 56",
            """
            <vertical_demo>
                <open56 src=" http://v.56.com/open_iframeplayer/3000005311_NjQzNTcxMDA.html" width="800" height="450" />
                <html_demo><div>Rate the video:</div></html_demo>
                <thumbs />
            </vertical_demo>
            """)
        ]

src、width、height属性将会映射到XBlock类中,并自动初始化所提供的值。你可以自由挑选你想在scenario中展示的视频

注册XBlock(入口点)

通过 entry_points mechanism of setuptools  XBlocks 会作为插件被自动加载。XBlocks是通过查找入口点的名称(xblock.v1处)完成注册。workbench会调用每一个已注册XBlocks的workbench_scenarios()方法,并将scenarios列表其显示在主页上
创建如下 xblock-open56/setup.py 文件:

fromsetuptools importsetup

    setup(
        name='xblock-open56',
        version='0.1',
        description='open56 XBlock Tutorial Sample',
        py_modules=['open56'],
        install_requires=['XBlock'],
        entry_points={
            'xblock.v1': [
                'open56 = open56:Open56Block',
            ]
        }
    )

然后创建一个文件xblock-open56/requirements.txt,写入必要的依赖包,本例中没有涉及,但在之后几篇文章中会用到(没错,本文章虽已发布,但开发分享还未结束~括弧,笑),但是本例中需要写入:

-e .

“-e’选项始终安装开发目录的最新文件,而不是当你运行该命令时先打包目录文件再安装。
然后运行pip去注册xblock-open56 ,让XBlock找到入口点

pip  install -r requirements.txt

然后(重新)启动workbench 服务器

cd ../xblock-sdk
python manage.py runserver 0.0.0.0:8000

如果上述步骤没有任何差错的话,你理应从http://IP:8000看到蓝色高亮的“Open 56” scenario


当你点击该链接,你应该看到56视频和一个简易的 thumb block


添加CSS:
比方说,我们要为每个视频框上下方添加边距,我们使用CSS来完成。创建 xblock-open56/static/css/open56.css 并写入如下代码:

    .open56{
        margin: 10px0;
    }

然后修改 Open56Block.student_view()方法

    class Open56Block(XBlock):
        [...]

        def student_view(self, context=None):
            """
            The primary view of the Open56Block, shown to students
            when viewing courses.
            """
            # Load the HTML fragment from within the package and fill in the template
            html_str =pkg_resources.resource_string(__name__, "static/html/open56_view.html")
            frag =Fragment(unicode(html_str).format(self=self, src=src, width=width, height=height))

            # Load CSS
            css_str =pkg_resources.resource_string(__name__, "static/css/open56.css")
            frag.add_css(unicode(css_str))
            return frag

重新载入 http://IP:8000/scenario/open56.0/ 应该就能够看到视频框上下边距了~

部署到Open edX

在Studio 和 LMS 使用Open56Block, 还需要做3件事:

  1. 确保ALLOW_ALL_ADVANCED_COMPONENTS feature 标识设置为True;
  2. 把 xblock-open56 安装到 studio 的 virtual environment;
  3. 在 Studio, 依次进入课程的 设置 -> 高级设置 把 “open56” 添加到 advanced_modules 列表中

假设你是以devstack启动的Open edX,你需要如下操作:

  1. ALLOW_ALL_ADVANCED_COMPONENTS 在devstack环境中已经被设置为 True,所以这一步不需要考虑.
  2. 最简单的做法是让你的本地文件夹(包含Open56Block代码的)能被devstack访问,如果你的devstack 是安装在Vagrant
    • 你可以添加以下代码到Vagrantfile ,然后重启devstack机器:
      config.vm.synced_folder "/path/to/xblock-open56", "/edx/xblock-open56", create: true, nfs: true
    • 然后 SSH 到 devstack 用pip 把 xblock-open56 安装到 edxapp environment :
      sudo  su  edxapp
      cd  /edx/xblock-open56
      pip  install  -r requirements.txt
  3. 重启 Studio, 点击你课程的导航栏 设置 -> 高级设置 , 将[“open56″] 添加到 advanced_modules

当你编辑一个单元的时候 你应该可以在“添加新组建” 中看到 “高级” 按钮。但你单击这个按钮, 你就可以在你的课程中添加 “Open56” XBlock


但实际上,该XBlock是不可用的,因为没有办法来设置src、Width和Height属性。

Studio 视图

为了实现“编辑” UI,我们在 Open56Block 类中添加studio_view方法:

def studio_view(self, context):
        """
        Create a fragment used to display the edit view in the Studio.
        """
        html_str =pkg_resources.resource_string(__name__, "static/html/open56_edit.html")
        src =self.src or''
        frag =Fragment(unicode(html_str).format(src=src, width=self.width, height=self.height))

        return frag

studio_view 方法看起来和student_view 方法类似,从静态模板构建一个frag
当用户打算编辑这个Block时static/html/open56_edit.html模板展示了一个表单:

<div class="wrapper-comp-settings is-active editor-with-buttons"id="settings-tab">
      <ul class="list-input settings-list">
        <li class="field comp-setting-entry is-set">
          <div class="wrapper-comp-setting">
            <label class="label setting-label"for="src">Video URL</label>
            <input class="input setting-input"name="src"id="src"value="{src}"type="text"/>
          </div>
          <span class="tip setting-help">Example:  http://v.56.com/open_iframeplayer/3000005311_NjQzNTcxMDA.html </span>
        </li>
        <li class="field comp-setting-entry is-set">
          <div class="wrapper-comp-setting">
            <label class="label setting-label"for="width">Width</label>
            <input class="input setting-input"name="width"id="width"value="{width}"type="text"/>
          </div>
          <span class="tip setting-help">width of the video player.</span>
        </li>
        <li class="field comp-setting-entry is-set">
          <div class="wrapper-comp-setting">
         <label class="label setting-label"for="height">Height</label>
            <input class="input setting-input"name="height"id="height"value="{height}"type="text"/>
          </div>
          <span class="tip setting-help">height of the video player.</span>
        </li>
      </ul>
      <div class="xblock-actions">
        <ul>
          <li class="action-item">
            <a href="#"class="button action-primary save-button">Save</a>
          </li>
          <li class="action-item">
            <a href="#"class="button cancel-button">Cancel</a>
          </li>
        </ul>
      </div>
    </div>

我们使用公共 Studio CSS 类 来修饰 form 让我们感觉这是Studio的一部分,而不至于太突兀.

在点击open56block右上角“编辑”按钮后你应该可以看到如下界面:


JavaScript & Ajax 调用

当前“Save” /“Cancel”按钮不会做任何事.为了让它真正实现保存属性的功能,我们在Open56VideoBlock 添加一个JSON handler,并添加一些必要的 JavaScript

为这一个 JSON handler 取名 studio_submit. 它用于实现 将已有属性设置为从POST request中取到的值。 如果在这里添加上一些验证逻辑自然是极好的,但本分享是基础分享,确保简单:

@XBlock.json_handler
    def studio_submit(self, data, suffix=''):
        """
        Called when submitting the form in Studio.
        """
        self.src =data.get('src')
        self.width =data.get('width')
        self.height =data.get('height')

        return{'result': 'success'}

static/js/src/open56_edit.js应该类似于:

functionOpen56EditBlock(runtime, element) {
      $(element).find('.save-button').bind('click', function() {
        varhandlerUrl = runtime.handlerUrl(element, 'studio_submit');
        vardata = {
          src: $(element).find('input[name=src]').val(),
          width: $(element).find('input[name=width]').val(),
          height: $(element).find('input[name=height]').val()
        };
        $.post(handlerUrl, JSON.stringify(data)).done(function(response) {
          window.location.reload(false);
        });
      });

      $(element).find('.cancel-button').bind('click', function() {
        runtime.notify('cancel', {});
      });
    }

我们为单击“保存”按钮事件附加了一个监听器,事件发生后将会POST属性值到 JSON handler
我们也为单击“取消”按钮事件附加了一个监听器,事件发生后将会调用runtime.notify(‘cancel’, {})来关闭当前编辑窗口
无论如何,我们需要将上述JavaScript 添加到 fragment:

def studio_view(self, context):
        """
        Create a fragment used to display the edit view in the Studio.
        """
        html_str =pkg_resources.resource_string(__name__, "static/html/simplevideo_edit.html")
        src =self.src or''
        frag =Fragment(unicode(html_str).format(href=src, width=self.width, height=self.height))

        js_str =pkg_resources.resource_string(__name__, "static/js/src/open56_edit.js")
        frag.add_javascript(unicode(js_str))
        frag.initialize_js('Open56EditBlock')

        return frag

现在,open56 block 基础版本开发结束~

本例代码:https://github.com/fmyzjs/xblock-open56

本例参考:https://antoviaque.org/docs/edx/xblock/tutorial.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值