##前言 上周部署了edX最新的release版本(release-2014-11-19),想看看有什么新的特性。

对比上回部署的版本release-2014-09-17,release-2014-11-19这个版本在部署的时候几乎不会遇到什么依赖问题。

当然,如果你想部署在阿里云上,可能还是蛮折腾的,主要是网络的问题,你懂的。而阿里云上vpn似乎很难使用,反正我没有成功过,配置成功过的同学求指教。我的方案是使用sshuttle,sshuttle也可能导致ip被影藏,ssh无法连接。应对这种问题你可以在启用sshuttle之前,使用ngrok把ssh端口映射出来。更多细节参考我之前的文章

release-2014-09-17部署的时候存在matplotlib依赖等问题。如果你部署的是release-2014-09-17版,建议移除edx_sandbox.yml中ora的安装。

此外,release-2014-11-19相对于release-2014-09-17另一个明显的变化是移动端接口被合并进来了(似乎是9-25号之后并入master的。如果你想使用edx的MOBILE_REST_API,9-25之后的release应该都是包含的。

顺便,再说一个可能潜在的问题。如果你设置了平台名字为中文(PLATFORM_NAME),那么你打开主讲教师tag时会出现500错误

错误的原因是lms/envs/common.py中有这句: ANALYTICS_DASHBOARD_NAME = ENV_TOKENS.get("ANALYTICS_DASHBOARD_NAME", PLATFORM_NAME + " Insights") ,log显示是字符编码错误。简易的处理方法是把写死ANALYTICS_DASHBOARD_NAME,比如ANALYTICS_DASHBOARD_NAME="ANALYTICS_DASHBOARD"

在汉化或者定制过程中可能遇到许多这类小错误,处理的思路是查看log,定位到问题所在,就可以干掉bug了。适当结合grep之类的工具会事半功倍,之后的文章中我会说说折腾edx中我自己常用的工具。它们大多来自linux工具箱

##开始 回到我们的主题,在此只记录我在release-2014-11-19上使用MOBILE_REST_API的过程。让其为移动端提供数据。

ok,let’s go

本篇文章针对生产环境,开发环境有些不同

##说明 edx的手机端接口需要身份验证(edX API Authentication),

我想使用基于Token的认证。 这一块是Django REST framework的内容,具体可参考django-rest-framework authentication中的TokenAuthentication部分,如果你想使用基于session或者OAuth2的认证也是可以的,事实上默认的就是SessionAuthentication和OAuth2Authentication。

##配置

MOBILE_REST_API默认并没有被启用,所以修改lms/envs/aws.py,启用它

  • diff –git a/lms/envs/aws.py b/lms/envs/aws.py 首先在aws.py最后添加以下内容

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    :::text
    +FEATURES['ENABLE_MOBILE_REST_API'] = True
    +FEATURES['ENABLE_VIDEO_ABSTRACTION_LAYER_API'] = True
    +
    +REST_FRAMEWORK = {
    +    'DEFAULT_AUTHENTICATION_CLASSES': (
    +        'rest_framework.authentication.BasicAuthentication',
    +        'rest_framework.authentication.SessionAuthentication',
    +        'rest_framework.authentication.TokenAuthentication',
    +		 'rest_framework.authentication.OAuth2Authentication',
    +    )
    +}

edx的手机端接口使用Django REST framework来写,我们所做的配置基本是Django REST framework的要求,跟edX关系不大。

  • diff –git a/lms/envs/common.py b/lms/envs/common.py

    1
    2
    3
    4
    5
    6
    7
    
    :::text
    INSTALLED_APPS = (
    
     # User API
     'rest_framework',
    +    'rest_framework.authtoken',
     'user_api',

##为UserDetail接口函数增加Token验证 diff –git a/lms/djangoapps/mobile_api/users/views.py b/lms/djangoapps/mobile_api/users/views.py

1
2
3
:::text
-from rest_framework.authentication import OAuth2Authentication, SessionAuthentication
+from rest_framework.authentication import OAuth2Authentication, SessionAuthentication,TokenAuthentication
1
2
3
:::text
-    authentication_classes = (OAuth2Authentication, SessionAuthentication)
+    authentication_classes = (TokenAuthentication,OAuth2Authentication, SessionAuthentication)

同理你也可以为其他接口函数做同样地工作。目前所有可以的接口如下

##同步数据库 由于我们在INSTALLED_APPS中增加了rest_framework.authtoken,所以需要同步一下数据库

1
2
sudo -u www-data /edx/bin/python.edxapp /edx/app/edxapp/edx-platform/manage.py lms --settings aws syncdb
sudo -u www-data /edx/bin/python.edxapp /edx/app/edxapp/edx-platform/manage.py lms --settings aws migrate

##重启生效

1
2
:::text
sudo /edx/bin/supervisorctl -c /edx/etc/supervisord.conf restart edxapp:

##开始测试 好啦,万事具备,我们来测试一下新加的手机端接口吧。

###获取Token

1
2
3
4
5
6
7
8
9
:::text
sudo -u www-data /edx/bin/python.edxapp /edx/app/edxapp/edx-platform/manage.py lms --settings aws shell


from rest_framework.authtoken.models import Token
from django.contrib.auth.models import User
user= User.objects.get(username="wwj")  #username填入你已注册的username
token = Token.objects.create(user=user)
print token.key

记下token.key的值,假设token是9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b,之后请求用户信息时需要携带它。

在生产环境中,你需要自己写个获取token的函数,在用户身份验证后返回token给他,比如取名request_token之类的。之后手机端获得token后,每次携带这个令牌来请求数据就好了

###获取用户详细信息 我们用curl去请求用户详细信息

1
2
:::text
curl -X GET http://127.0.0.1:8000/api/mobile/v0.5/users/ww -H 'Authorization:Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'

你将获取以下内容

1
2
:::text
{"id": 6, "username": "wwj", "email": "wwj@qq.com", "name": "wwj", "course_enrollments": "http://127.0.0.1:8000/api/mobile/v0.5/users/ww/course_enrollments/"}

返回参数的意义如下:

  • id: 用户id
  • username: 用户名
  • email: 用户的email
  • name: 用户的全名
  • course_enrollments: 用户注册课程列表

ok,一切正常

以上只是粗粗地介绍了主要原理,如果你想在实际生产环境中使用,需要自己去完成一下request_token函数

#参考资料 * edx-platform-api * django-rest-framework authentication