尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Open edX Learner Home 模块解析:学生仪表盘 MFE 的后端 API 与实现
Open edX Learner Home 模块解析学生仪表盘 MFE 的后端 API 与实现【免费下载链接】openedx-platformThe Open edX LMS Studio, powering education sites around the world!项目地址: https://gitcode.com/GitHub_Trending/ed/openedx-platform导读Learner Home 是 Open edX 平台面向学习者的全新课程仪表盘student dashboard后端实现它以 REST API 的形式为前端微前端MFE提供我的课程列表所需的全部数据。本文以仓库中 lms/djangoapps/learner_home/README.md 为骨架结合源码、路由、序列化器与设计文档完整剖析该模块的定位、数据装配流水线、序列化模型、可扩展点与功能开关帮助开发者理解并二次开发这一核心学生页面。Learner Home 是什么定位与目标按 README 的说明This is the new dashboard for learner courses, built as a backend supporting a new MFE experience of the student dashboard. This aims to replace the existing dashboard at:/common/djangoapps/student/views/dashboard.py定位面向学习者课程的新仪表盘是全新 MFE 体验学生仪表盘的后端支撑目标替代旧的仪表盘实现即 common/djangoapps/student/views/dashboard.py。旧仪表盘是一个由 Django 服务端渲染server-rendered的整页模板负责把注册课程、证书、成绩等数据拼装后直接渲染 HTMLLearner Home 则把这一整套逻辑下沉为 JSON API由独立的前端 MFE 消费从而实现前后端解耦、前端可独立演进。从源码看views.py 仍从旧的dashboard.py中导入complete_course_mode_info、credit_statuses、get_course_enrollments、get_filtered_course_entitlements、get_org_black_and_whitelist_for_site等既有工具函数说明新旧实现共享同一批领域逻辑Learner Home 是复用逻辑、换掉渲染层的迁移方案。模块结构与目录布局Learner Home 位于lms/djangoapps/learner_home/从目录结构可以看到清晰的职责划分路径职责views.py核心视图与全部数据装配函数get_*系列serializers.pyDRF 序列化器定义 API 响应契约utils.py辅助工具masquerade 用户解析、课程进度 URL 生成waffle.pyLearner Home MFE 功能开关Waffle Flagurls.py应用内路由init、mock、rest_apirest_api/挂载 Programs REST API v1mock/静态 Mock 视图与数据mock_data.jsondocs/架构决策记录ADR这种按功能分层、单文件单职责的组织方式正是设计文档 002-core-versus-experimental-code.rst 所倡导的核心功能与实验性代码物理隔离避免代码膨胀、降低调试时的认知负担。URL 路由与 API 入口在 lms/urls.py 中注册了命名空间路由path(api/learner_home/, include(lms.djangoapps.learner_home.urls, namespacelearner_home)),应用内部路由定义在 urls.pyapp_name learner_home urlpatterns [ re_path(r^init/?, views.InitializeView.as_view(), nameinitialize), path(mock/, include(lms.djangoapps.learner_home.mock.urls)), path(, include(rest_api_urls)), ]由此可以得到三条主要路由GET /api/learner_home/init/—— 核心接口返回学习者仪表盘初始化所需的全部数据下文详解GET /api/learner_home/mock/...—— 返回 mock/mock_data.json 中静态编写的 JSON用于前端在无后端数据时的联调与页面开发mock_views.py 注释 Edit me to change response data 说明数据可手工编辑/api/learner_home/.../v1/...—— 挂载 Programs 的 v1 REST APIrest_api/urls.py用于课程卡片中展示关联的项目Program信息。核心接口 InitializeView 的认证与授权InitializeView 是 DRF 的APIView其认证与权限配置如下class InitializeView(APIView): authentication_classes ( JwtAuthentication, BearerAuthenticationAllowInactiveUser, SessionAuthenticationAllowInactiveUser, ) permission_classes (IsAuthenticated, NotJwtRestrictedApplication) def get(self, request, *args, **kwargs): masquerade_user get_masquerade_user(request) if masquerade_user: return self._initialize(masquerade_user, is_masqueradeTrue) else: return self._initialize(request.user)要点三种认证方式并存JWTMFE 通常携带的凭据、Bearer Token允许未激活用户用于账号未激活但仍需看到待办事项的场景、Session 认证权限必须已认证且排除受限 JWT 应用NotJwtRestrictedApplication避免服务间调用的受限凭据直接访问学生个人数据支持 masquerade扮演详见下文调试与扩展一节。数据装配流水线一次 init 请求背后发生了什么_initialize方法是整个模块的数据中枢views.py它依次调用一组get_*函数收集数据最后交给序列化器输出。完整调用序列如下数据块装配函数说明emailConfirmationget_user_account_confirmation_info判断账号是否需要激活返回激活邮件发送地址enterpriseDashboardget_enterprise_customer企业客户信息可被插件覆盖见后文socialShareSettingsget_social_share_settingsFacebook / Twitter 分享配置与 UTM 参数platformSettingsget_platform_settings平台级配置支持邮箱、账单邮箱、课程搜索 URL站点黑白名单get_org_block_and_allow_lists代理旧 dashboard 的机构黑白名单逻辑entitlementsget_entitlements区分已满足/未满足的课程权益附带可选课程时段enrollmentsget_enrollments拉取注册列表并按注册时间倒序排序audit_access_deadlinesget_audit_access_deadlines审计模式audit课程访问过期时间email settingsget_email_settings_info哪些课程开启了群发邮件、用户是否已退订grade_statusesget_user_grade_passing_statuses每门课程是否达到及格线cert_statusesget_cert_statuses每门课程的证书状态course_access_checkscheck_course_access能否访问课程内容前置未满足/未开课/员工权限programsget_course_programs课程所属项目及其关联项目ecommerce_payment_pageget_ecommerce_payment_page电商支付页 URL若启用resume_course_urlsget_resume_urls_for_course_enrollments每门课的继续学习跳转链接suggestedCoursesget_suggested_courses推荐课程默认读取平台配置course_share_urlsget_course_share_urls课程的社交分享 URLcredit_statusesget_credit_statuses学分credit状态这些函数大多有function_trace装饰器说明每个数据块都纳入 edX 监控系统的性能追踪便于定位单次 init 请求中的耗时热点。数据最终被分为两组传入序列化learner_dash_data { emailConfirmation: email_confirmation, enterpriseDashboard: enterprise_customer, platformSettings: platform_settings, enrollments: course_enrollments, unfulfilledEntitlements: unfulfilled_entitlements, socialShareSettings: social_share_settings, suggestedCourses: suggested_courses, } context { ... } # 其余派生数据统一放入 context供序列化器按需读取这种原始数据 派生上下文的拆分避免了对数据库的重复查询——例如课程模式CourseMode信息只加载一次便供多个序列化器复用见 get_enrollments 中的注释 We re-use the course modes dict we loaded earlier to avoid hitting the database。部分关键函数的实现细节get_enrollments调用旧仪表盘的get_course_enrollments获取注册按created字段倒序排序同时加载每门课程的CourseMode并调用complete_course_mode_info生成升级销售upsell信息还会通过monitoring_utils.accumulate(num_courses, ...)上报课程数量指标用于观测生产环境的负载分布。get_resume_urls_for_course_enrollments基于 completion 服务get_key_to_last_completed_block找到用户最后完成的单元构造jump_to反向 URL若用户尚未开始课程则返回None捕捉UnavailableCompletionData异常。get_cert_statuses逐门课程调用cert_info并捕获异常注释 APER-2171 指出为已删除课程获取证书可能抛异常保证单门课程异常不影响整个接口。check_course_access输出每门课程的has_unmet_prerequisites前置课程未完成、is_too_early_to_view课程未开课、user_has_staff_access用户是否拥有员工权限对应旧仪表盘中show_courseware_links_for的判定逻辑见 serializers.py 的注释。序列化层课程卡片的 JSON 契约响应序列化由 LearnerDashboardSerializer 完成其courses字段将注册列表与未满足权益列表拍平成一个统一的课程卡片数组def get_courses(self, instance): courses [] for enrollment in instance.get(enrollments, []): courses.append(LearnerEnrollmentSerializer(enrollment, contextself.context).data) for entitlement in instance.get(unfulfilledEntitlements, []): courses.append(UnfulfilledEntitlementSerializer(entitlement, contextself.context).data) return courses已注册课程由 LearnerEnrollmentSerializer 序列化嵌套包含course课程头信息、courseProvider机构、courseRun课程期次、enrollment注册状态、certificate证书、entitlement对应权益、gradeData成绩、programs关联项目、credit学分九大块未满足权益买了课程权益但尚未选课由 UnfulfilledEntitlementSerializer 序列化与注册卡片保持相同的键结构前端因此可以用同一套课程卡片组件渲染两类数据其中enrollment等字段通过自定义的 LiteralField 输出固定静态值如mode: null、isEnrolled: false其余真实字段entitlement、course、courseProvider、programs正常序列化。各嵌套序列化器值得注意的派生字段字段来源逻辑courseRun.isStarted/isArchivedCourseOverview.has_started()/has_ended()课程是否已开始 / 已结束courseRun.resumeUrlcontext 中的resume_course_urls继续学习跳转链接courseRun.upgradeUrlecommerce_payment_pageverified_sku仅当启用电商支付且存在升级 SKU 时生成带sku、course_run_key参数的升级链接courseRun.unenrollUrlreverse(course_run_refund_status)退课/退款状态页enrollment.isAuditmode in CourseMode.AUDIT_MODES是否审计模式enrollment.canUpgrade电商支付页 show_upsellverified_sku三者同时成立能否升级到认证verified轨道enrollment.isAuditAccessExpiredcontext 中预取的过期时间镜像旧仪表盘check_course_expired逻辑但使用预取数据certificate.isRestricted/isEarned/isDownloadable证书状态字符串状态为restricted、downloadable、certificate_earned_but_not_available等certificate.availableDatecertificates_display_behavior依据CertificatesDisplayBehaviors.END_WITH_DATE/END决定展示行为取自 xmodule/data.py内置的过滤器扩展点两个核心序列化器都在渲染完成时触发了 openedx-filters 事件serializers.py 与 serializers.pyCourseRunAPIRenderStartedfilter typeorg.openedx.learning.home.courserun.api.rendered.started.v1在课程期次 JSON 渲染完成后回调允许插件二次修改期次数据CourseEnrollmentAPIRenderStartedfilter typeorg.openedx.learning.home.enrollment.api.rendered.v1在注册卡片渲染完成后回调可注入自定义注册信息。第三方插件通过订阅这些过滤器即可在不改动核心代码的前提下定制课程卡片内容这也是 002 号设计文档实验不侵入核心原则的落地体现之一。调试与扩展masquerade、可插拔覆盖与 Mock 数据Masquerade扮演机制在 utils.py 中get_masquerade_user支持通过GET /api/learner_home/init/?userusername或email以他人身份查看仪表盘只有is_staff用户可以使用该参数否则抛出PermissionDenied用户不存在时返回NotFound当标识符同时命中多个用户时记录日志并回退为按 username 精确匹配命中后记录一条形如[Learner Home] staff masquerades as learner的日志便于审计。这是支撑客服support工具与员工预览学生视角页面的关键能力。可插拔覆盖点get_enterprise_customer使用了pluggable_override(OVERRIDE_LEARNER_HOME_GET_ENTERPRISE_CUSTOMER)装饰器views.py并通过 EnterpriseCustomerData 这一TypedDict定义了返回契约name、uuid、slug、auth_org_id、enable_learner_portal。安装的插件可通过该设置项替换默认实现默认返回None从而接入企业enterprise学习门户数据无需修改核心代码。静态 Mock 数据mock/mock_views.py 提供一个RetrieveAPIView直接读取同目录下的 mock_data.json 并原样返回。该路由仅用于本地前端开发当后端数据不可用或不希望依赖真实用户数据时通过编辑 JSON 文件即可模拟任意响应形态文件头注释明确写着 Edit me to change response data。功能开关Waffle Flag 与站点配置Learner Home MFE 是否生效由 waffle.py 中的开关控制WAFFLE_FLAG_NAMESPACE learner_home_mfe ENABLE_LEARNER_HOME_MFE WaffleFlag( f{WAFFLE_FLAG_NAMESPACE}.enabled, # 即 learner_home_mfe.enabled __name__, )Flag 名称learner_home_mfe.enabled默认关闭toggle_default: False创建于 2022-10-11票据 AU-879用途是开启后将用户重定向到 Learner Home MFElearner_home_mfe_enabled()优先读取站点配置Site Configuration中的ENABLE_LEARNER_HOME_MFE覆盖值其次才回落到 Waffle Flag 本身——这意味着运营方可以按站点、按用户群精细化灰度而无需改动代码。两个关键架构决策ADR决策一移除课程数量上限文档 001-remove-course-limit.rst 记录了旧仪表盘的DASHBOARD_COURSE_LIMIT250 门限制旧页面默认只展示前 250 门课程超出后由用户手动点击显示全部。由于新仪表盘需要本地排序与筛选若继续截断数据会导致排序/筛选不完整的体验缺陷因此新实现移除课程数量上限默认展示全部课程。该决策带来的后果按使用数据抽样约 0.2% 的用户达到或超过旧上限因此影响面较小潜在代价是整页加载时间变长、后端系统资源占用上升曾考虑的两个替代方案设计分页查询系统技术工作量不明确、保留上限并提供手动展开被否决因为会导致筛选不完整。决策二核心代码与实验代码分离文档 002-core-versus-experimental-code.rst 明确了新 Learner Home 的目标之一是提供功能实验experimentation的入口例如前端单独的小组件推荐课程。为保证核心能力展示注册/权益的稳定性实验功能不得修改主init接口而应作为独立视图/API 存在理想情况下放在learner_home下的独立子目录中这样实验代码的缺陷或回归只会影响依赖该实验的容器/组件核心页面保持相对稳定可靠代价是文件/目录数量增加但换来的是文件更单一职责、认知负荷更低。仓库中mock/、rest_api/等子目录的物理分隔正是这一原则的直接体现。测试覆盖模块自带完整的单元测试与集成测试可作为理解行为契约的活文档test_views.py913 行覆盖各get_*装配函数与InitializeView使用ddt参数化、patch模拟设置如DEFAULT_FEEDBACK_EMAIL、PAYMENT_SUPPORT_EMAIL并通过CourseEnrollmentFactory、CourseOverviewFactory、CourseEntitlementFactory、ProgramFactory等工厂构造数据test_serializers.py验证各序列化器字段输出特别是课程卡片、证书、权益、学分等派生字段test_utils.py测试辅助工具create_test_enrollment、random_string、random_urltest_waffle.py验证learner_home_mfe_enabled()对站点配置与 Waffle Flag 的读取逻辑。例如测试中对get_platform_settings的用例展示了该函数如何读取DEFAULT_FEEDBACK_EMAIL、PAYMENT_SUPPORT_EMAIL并在启用 Catalog MFE 时以settings.CATALOG_MICROFRONTEND_URL/courses作为课程搜索地址views.py完整闭环可读。总结Learner Home 是 Open edX 从服务端渲染仪表盘向MFE REST API演进中的关键后端模块。它以/api/learner_home/init/单一入口聚合了注册、权益、证书、成绩、课程模式、项目、学分、推荐等十余类数据通过分层序列化器输出统一的课程卡片 JSON 契约并通过 Waffle Flag、站点配置、可插拔函数覆盖、openedx-filters 过滤器等机制提供多级扩展点同时以 ADR 形式固化了移除课程上限与核心/实验代码隔离两项架构决策。对需要定制学习者仪表盘、接入企业门户或做前端实验的开发者而言本模块是理解 Open edX 现代化学生体验的最佳起点。【免费下载链接】openedx-platformThe Open edX LMS Studio, powering education sites around the world!项目地址: https://gitcode.com/GitHub_Trending/ed/openedx-platform创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

SeaTunnel HBase Source Connector 完全指南:批量扫描、RowKey 与时间范围读取实战

SeaTunnel HBase Source Connector 完全指南:批量扫描、RowKey 与时间范围读取实战

SeaTunnel HBase Source Connector 完全指南:批量扫描、RowKey 与时间范围读取实战 【免费下载链接】seatunnel SeaTunnel is a multimodal, high-performance, distributed, massive data integration tool. 项目地址: https://gitcode.com/GitHub_Trending/se/s…

📅 2026/9/17 18:13:27
画 Baseten Hosted Tools 调用图,TaoToken Key 标出 Token 消耗

画 Baseten Hosted Tools 调用图,TaoToken Key 标出 Token 消耗

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/17 18:13:27
Node.js v12.11.0 (Current) 版本发布全解析:worker_threads 转正、V8 7.7 升级与 SourceMap 覆盖支持

Node.js v12.11.0 (Current) 版本发布全解析:worker_threads 转正、V8 7.7 升级与 SourceMap 覆盖支持

Node.js v12.11.0 (Current) 版本发布全解析:worker_threads 转正、V8 7.7 升级与 SourceMap 覆盖支持 【免费下载链接】nodejs.org The Node.js Website 项目地址: https://gitcode.com/GitHub_Trending/no/nodejs.org 2019 年 9 月 25 日,Node.…

📅 2026/9/17 18:08:26
MORE NEWS

更多资讯

📰

零基础选AI工具的3个关键问题决策法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

ROS2 Ubuntu安装教程:版本对应、apt源、环境变量与验证

1. 先别急着敲apt:ROS2与Ubuntu的版本对应关系ROS2在Ubuntu中安装这件事,看起来只是几条apt命令,但真正上手时,版本对应、软件源、环境变量这三关就能让不少人反复重装系统。我见过太多刚接触机器人开发的朋友,兴冲冲地…

📰

CiA402伺服协议详解:状态机、对象字典与多模式切换实战

伺服调试这行干久了,会发现一个挺有意思的现象:很多人能把 CANopen 的报文收发写得明明白白,SDO 读写、PDO 映射、心跳、NMT 状态机这些玩得挺溜,可一旦要用 CiA402 去驱动一台真正带轴的伺服,就开始卡壳——使能不了、…

📰

超薄设备开关机电路极简设计:无需MCU的25nA方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

UL 943-2018 GFCI安规设计与型式试验实战指南

简介:本资源为美国UL认证机构发布的最新版《UL 943-2018 Ground-Fault Circuit-Interrupters》安全标准全文PDF,面向电气工程师、产品认证人员、GFCI研发与测试技术人员及高校相关专业师生,用于指导漏电保护断路器的设计合规性验证、型式试验…

📰

Python aggregate-prefixes 包实战案例与常见错误

1. 引言在网络工程与自动化运维领域,IP 地址前缀(Prefix)的聚合是一项常见且重要的操作。无论是 BGP 路由表优化、防火墙策略收敛,还是云网络规划,都需要将大量分散的前缀合并为更紧凑的 CIDR 块。Python 生态中&#…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬