访问Moodle服务器';通过Python';s请求库
我正在尝试使用Python的请求库访问Moodle安装的web服务。我有API的文档和一个用php编写的示例项目(我以前没有看过php,比我预期的要难理解得多),但我确实很难正确格式化请求。该站点正在返回检测到的无效参数,因此我非常确定我的端点、授权令牌和服务器配置正在工作,这正是让我失望的数据格式 首先这里是错误访问Moodle服务器';通过Python';s请求库,python,rest,python-requests,moodle,moodle-api,Python,Rest,Python Requests,Moodle,Moodle Api,我正在尝试使用Python的请求库访问Moodle安装的web服务。我有API的文档和一个用php编写的示例项目(我以前没有看过php,比我预期的要难理解得多),但我确实很难正确格式化请求。该站点正在返回检测到的无效参数,因此我非常确定我的端点、授权令牌和服务器配置正在工作,这正是让我失望的数据格式 首先这里是错误 <?xml version="1.0" encoding="UTF-8" ?> <EXCEPTION class="invalid_parameter_except
<?xml version="1.0" encoding="UTF-8" ?>
<EXCEPTION class="invalid_parameter_exception">
<ERRORCODE>invalidparameter</ERRORCODE>
<MESSAGE>Invalid parameter value detected</MESSAGE>
</EXCEPTION>
这是网站的文档
最后是php中的示例
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>V6</title>
</head>
<body>
<?php
//load curl.php
require_once('curl.php');
function randomPassword() //according to Moodle password requirements
{
$part1 = "";
$part2 = "";
$part3 = "";
//alphanumeric LOWER
$alphabet = "abcdefghijklmnopqrstuwxyz";
$password_created = array(); //remember to declare $pass as an array
$alphabetLength = strlen($alphabet) - 1; //put the length -1 in cache
for ($i = 0; $i < 3; $i++)
{
$pos = rand(0, $alphabetLength); // rand(int $min , int $max)
$password_created[] = $alphabet[$pos];
}
$part1 = implode($password_created); //turn the array into a string
//echo"<br/>part1 = $part1";
//alphanumeric UPPER
$alphabet = "ABCDEFGHIJKLMNOPQRSTUWXYZ";
$password_created = array(); //remember to declare $pass as an array
$alphabetLength = strlen($alphabet) - 1; //put the length -1 in cache
for ($i = 0; $i < 3; $i++)
{
$pos = rand(0, $alphabetLength); // rand(int $min , int $max)
$password_created[] = $alphabet[$pos];
}
$part2 = implode($password_created); //turn the array into a string
//echo"<br/>part2 = $part2";
//alphanumeric NUMBER
$alphabet = "0123456789";
$password_created = array(); //remember to declare $pass as an array
$alphabetLength = strlen($alphabet) - 1; //put the length -1 in cache
for ($i = 0; $i < 2; $i++)
{
$pos = rand(0, $alphabetLength); // rand(int $min , int $max)
$password_created[] = $alphabet[$pos];
}
$part3 = implode($password_created); //turn the array into a string
//echo"<br/>part3 = $part3";
$password = $part1 . $part2 . $part3 . "#";
return $password;
}
function getCDate()
{
$format = "Ymd";
$fulldate = date($format);
//echo"<br/>fulldate = $fulldate";
return $fulldate;
}
function enrol($user_id, $course_id)
{
$role_id = 5; //assign role to be Student
$domainname = 'http://www.yoursite.eu'; //paste your domain here
$wstoken = '8486ed14f3ghjec8967a0229d0a28zzz'; //here paste your enrol token
$wsfunctionname = 'enrol_manual_enrol_users';
$enrolment = array( 'roleid' => $role_id, 'userid' => $user_id, 'courseid' => $course_id );
$enrolments = array($enrolment);
$params = array( 'enrolments' => $enrolments );
header('Content-Type: text/plain');
$serverurl = $domainname . "/webservice/rest/server.php?wstoken=" . $wstoken . "&wsfunction=" . $wsfunctionname;
$curl = new curl;
$restformat = ($restformat == 'json')?'&moodlewsrestformat=' . $restformat:'';
$resp = $curl->post($serverurl . $restformat, $params);
print_r($resp);
}
function getUserDetails()
{
$firstname = "TestUser";
$lastname = "TestUser";
$email = "TestUser@zzz.gr";
$city = "Thessaloniki";
$country = "EL";
$description= "ZZZ";
//assign username
//get first two letters of name and surname
//$strlength_user = strlen($firstname);
//$strlength_pass = strlen($lastname);
$rest_firstname = substr($firstname, 0, 2);
$rest_lastname = substr($lastname, 0, 2);
$part1 = $rest_firstname . $rest_lastname;
$part1 = strtolower($part1);
//echo"<br/>part1 = $part1";
$dt = getCDate();
$part2 = substr($dt, -4);
//echo"<br/>part2 = $part2";
$username = $part1 . "." . $part2;
echo"<br/>Username = $username";
//assign password
$password = randomPassword();
echo"<br/>Password = $password";
//call WS core_user_create_user of moodle to store the new user
$domainname = 'http://www.yoursite.eu';
$wstoken = 'ed1f6d3ebadg372f95f28cd96bd43zzz'; //here paste your create user token
$wsfunctionname = 'core_user_create_users';
//REST return value
$restformat = 'xml';
//parameters
$user1 = new stdClass();
$user1->username = $username;
$user1->password = $password;
$user1->firstname = $firstname;
$user1->lastname = $lastname;
$user1->email = $email;
$user1->auth = 'manual';
$user1->idnumber = 'numberID';
$user1->lang = 'en';
$user1->city = $city;
$user1->country = $country;
$user1->description = $description;
$users = array($user1);
$params = array('users' => $users);
//REST call
header('Content-Type: text/plain');
$serverurl = $domainname . "/webservice/rest/server.php?wstoken=" . $wstoken . "&wsfunction=" . $wsfunctionname;
$curl = new curl;
$restformat = ($restformat == 'json')?'&moodlewsrestformat=' . $restformat:'';
$resp = $curl->post($serverurl . $restformat, $params);
print_r($resp);\
//get id from $resp
$xml_tree = new SimpleXMLElement($resp);
print_r($xml_tree);
$value = $xml_tree->MULTIPLE->SINGLE->KEY->VALUE;
$user_id = intval(sprintf("%s",$value));
echo"<br/>user_id number = $user_id";
//enrol_manual_enrol_users
//for($i = 64; $i < 70; $i++) //where 64,65,66,67,68,69 are the six ids of the six courses of phase 1
for($i = 64; $i < 65; $i++)
{
echo "\nThe user has been successfully enrolled to course " . $i;
$course_id = $i;
enrol($user_id, $course_id);
}
}
getUserDetails();
?>
</body>
</html>
V6
用户名=$username;
$user1->password=$password;
$user1->firstname=$firstname;
$user1->lastname=$lastname;
$user1->email=$email;
$user1->auth='manual';
$user1->idnumber='numberID';
$user1->lang='en';
$user1->city=$city;
$user1->country=$country;
$user1->description=$description;
$users=数组($user1);
$params=array('users'=>$users);
//休息电话
标题(“内容类型:文本/普通”);
$serverurl=$domainname。“/webservice/rest/server.php?wstoken=“$沃斯托肯。“&wsfunction=”$wsfunctionname;
$curl=新的curl;
$restformat=($restformat='json')?'&moodlewsrestformat='$REST格式:'';
$resp=$curl->post($serverurl.$restformat,$params);
印刷费($resp)\
//从$resp获取id
$xml_tree=新的SimpleXMLElement($resp);
打印(xml树);
$value=$xml_-tree->MULTIPLE->SINGLE->KEY->value;
$user_id=intval(sprintf(“%s”,$value));
echo“
用户标识号=$user\u id”;
//注册用户手册注册用户
//对于($i=64;$i<70;$i++)//其中64,65,66,67,68,69是第一阶段六个课程的六个ID
对于($i=64;$i<65;$i++)
{
echo“\n用户已成功注册课程”。$i;
$course\u id=$i;
注册($user\u id,$course\u id);
}
}
getUserDetails();
?>
好吧,我找到了一个可行的解决方案,但我怀疑这有点大杂烩,没有充分利用请求库
我所做的是将所有参数作为参数传递到url中
target = 'http://example.com/moodle/webservice/rest/server.php'
moodle_create_token = 'xxx'
payload = {
"wstoken":moodle_create_token,
"moodlewsrestformat":"json", #just to get response as json
"wsfunction":"core_user_create_users",
"users[0][username]":"testusername",
"users[0][password]":'testpassword',
"users[0][firstname]":'testfirstname',
"users[0][lastname]":'testlastname',
"users[0][email]":"testemail@example.com",
"users[0][idnumber]":"0000001"
}
r=requests.post(target, params=payload)
显然,我通常不会将数据硬编码为字符串,但显然url参数的字典列表是。下面是一个示例,展示了如何使用Python的
请求来访问Moodle Web Services API:
from requests import get, post
# Module variables to connect to moodle api
KEY = "SECRET API KEY"
URL = "https://moodle.site.com"
ENDPOINT="/webservice/rest/server.php"
def rest_api_parameters(in_args, prefix='', out_dict=None):
"""Transform dictionary/array structure to a flat dictionary, with key names
defining the structure.
Example usage:
>>> rest_api_parameters({'courses':[{'id':1,'name': 'course1'}]})
{'courses[0][id]':1,
'courses[0][name]':'course1'}
"""
if out_dict==None:
out_dict = {}
if not type(in_args) in (list,dict):
out_dict[prefix] = in_args
return out_dict
if prefix == '':
prefix = prefix + '{0}'
else:
prefix = prefix + '[{0}]'
if type(in_args)==list:
for idx, item in enumerate(in_args):
rest_api_parameters(item, prefix.format(idx), out_dict)
elif type(in_args)==dict:
for key, item in in_args.items():
rest_api_parameters(item, prefix.format(key), out_dict)
return out_dict
def call(fname, **kwargs):
"""Calls moodle API function with function name fname and keyword arguments.
Example:
>>> call_mdl_function('core_course_update_courses',
courses = [{'id': 1, 'fullname': 'My favorite course'}])
"""
parameters = rest_api_parameters(kwargs)
parameters.update({"wstoken": KEY, 'moodlewsrestformat': 'json', "wsfunction": fname})
response = post(URL+ENDPOINT, parameters).json()
if type(response) == dict and response.get('exception'):
raise SystemError("Error calling Moodle API\n", response)
return response
class CourseList():
"""Class for list of all courses in Moodle and order them by id and idnumber."""
def __init__(self):
# TODO fullname atribute is filtered
# (no <span class="multilang" lang="sl">)
courses_data = call('core_course_get_courses')
self.courses = []
for data in courses_data:
self.courses.append(Course(**data))
self.id_dict = {}
self.idnumber_dict = {}
for course in self.courses:
self.id_dict[course.id] = course
if course.idnumber:
self.idnumber_dict[course.idnumber] = course
def __getitem__(self, key):
if 0<= key < len(self.courses):
return self.courses[key]
else:
raise IndexError
def by_id(self, id):
"Return course with given id."
return self.id_dict.get(id)
def by_idnumber(self, idnumber):
"Course with given idnumber"
return self.idnumber_dict.get(idnumber)
def update_courses(courses_to_update, fields):
"Update a list of courses in one go."
if not ('id' in fields):
fields.append('id')
courses = [{k: c.__dict__[k] for k in fields} for c in courses_to_update]
return call("core_course_update_courses",
courses = courses)
从请求导入获取,发布
#要连接到moodle api的模块变量
KEY=“机密API密钥”
URL=”https://moodle.site.com"
ENDPOINT=“/webservice/rest/server.php”
def rest_api_参数(in_参数,前缀=“”,out_dict=无):
“”“将字典/数组结构转换为具有键名称的平面字典
定义结构。
用法示例:
>>>rest_api_参数({'courses':[{'id':1,'name':'course1'}]})
{'0][id]':1,
“课程[0][name]:“课程1'}
"""
如果out_dict==无:
out_dict={}
如果不在(列表,目录)中键入(在参数中):
out\u dict[前缀]=in\u参数
退票
如果前缀=“”:
前缀=前缀+“{0}”
其他:
前缀=前缀+'[{0}]'
如果类型(在参数中)=列表:
对于idx,枚举中的项(在参数中):
rest\u api\u参数(项,前缀.格式(idx),输出)
elif类型(在参数中)=dict:
对于键,参数项()中的项:
rest\u api\u参数(项、前缀、格式(键)、输出)
退票
def呼叫(fname,**kwargs):
“”“使用函数名fname和关键字参数调用moodle API函数。
例子:
>>>调用函数(“核心课程更新课程”,
课程=[{'id':1,'fullname':'My favorite course'}])
"""
参数=剩余api参数(kwargs)
update({“wstoken”:KEY,'moodlewsrestformat':'json',“wsfunction”:fname})
response=post(URL+端点,参数).json()
如果type(response)=dict和response.get('exception'):
raise SystemError(“调用Moodle API时出错,\n”,响应)
返回响应
类CourseList():
“”“为Moodle中所有课程的列表上课,并按id和idnumber排序。”“”
定义初始化(自):
#TODO全名atribute已筛选
#(否)
课程\数据=呼叫(“核心\课程\获取\课程”)
self.courses=[]
对于课程和大学数据中的数据:
self.courses.append(课程(**数据))
self.id_dict={}
self.idnumber_dict={}
对于自学课程:
self.id\u dict[course.id]=课程
如果是course.idnumber:
self.idnumber\u dict[course.idnumber]=课程
def _u获取项目(自身,密钥):
如果0我创建了一个名为
例如,它很容易使用
from moodle import Moodle
target = 'http://example.com/moodle/webservice/rest/server.php'
moodle_create_token = 'xxx'
moodle = Moodle(target, moodle_create_token)
r = moodle(
'core_user_create_users',
username="testusername",
password='testpassword',
firstname='testfirstname',
lastname='testlastname',
email="testemail@example.com",
idnumber="0000001"
) # return the data (dict, list, etc)
您还可以使用类型化响应,例如调用core\u webservice\u get\u site\u info
site_info = moodle.core.webservice.get_site_info()
site_info.username
site_info.version
注意:并非所有功能都已实现。请尝试将data=payload
更改为json=payload
,谢谢我以前尝试过。我认为问题在于我传递的数据的嵌套。我正在发送一个单级结构。。。data=[pair 1,pair 2,pair 3]其中我需要做的是更深层次的事情user=[pair 1,pair 2,pair 3]data=[user[]我就是不能让它完全工作。
from moodle import Moodle
target = 'http://example.com/moodle/webservice/rest/server.php'
moodle_create_token = 'xxx'
moodle = Moodle(target, moodle_create_token)
r = moodle(
'core_user_create_users',
username="testusername",
password='testpassword',
firstname='testfirstname',
lastname='testlastname',
email="testemail@example.com",
idnumber="0000001"
) # return the data (dict, list, etc)
site_info = moodle.core.webservice.get_site_info()
site_info.username
site_info.version