站点运行环境
直接在站点服务上运行,可以访问整个站点的所有内容
1 通过Web访问
1.1 浏览器地址栏直接访问
这种方法,在前端教程已经讲过。在浏览器中访问方法为:
http://<站点域名:端口>/对象地址/@<应用名>:<脚本名>
- 脚本内可以使用context、request、view等变量(具体解释见后)
- 会检查是否有权限调用
输出结果会组装到系统的皮肤模板:
如果返回字符串,直接填充到了main区域
也可以返回一个dict,填充模板各个区域:
{'main': '', # 主正文区域 'left': '', # 左侧区域,通常是导航栏 'right': '', # 右侧区域,通常是附加辅助信息 'side': '', # 侧边悬浮区,用于反馈问题、网站编辑工具,回到顶部等按钮 'title': '', # 页面标题 'description': '' # 页面描述信息}
上面dict中的每个值,可以是包含html内容的字符串,也可以是ui组件(如: (ui.h1('我们'))。
地址中的参数,会直接传递到脚本中的对应参数,比如:
http://path/to/script?aa=1&bb=2
也可以支持参数后缀(:int, :float, :boolean, :list 等),来定义参数类型,平台自动会做类型转换,比如:
http://path/to/script?aa:int=1&bb:float=2
传递的参数可在request中获取:
- request['aa'] 里面直接就是对应的数据类型(整数、布尔、列表等),不需要在转换
- 如果脚本包含了同名的参数,比如 aa, bb ,会直接赋值到参数,不需要从request中获取
(注:如果看到含有 @@ 的地址,这些属于平台底层的内置脚本,不属于软件包)
1.2 通过RESTful API来调用
所有脚本都可以直接通过RESTful API进行调用,地址为:
/api/v3/x-api/<应用名>:<脚本名>
也可以直接通过edo_client的 xapi 方法来调用,比如:
wo_client = root.get_client(request, 'workonline', site_name) result = wo_client.xapi('xxx.xxx:xxx', aa=1, bb=2)
1.3 前端组件Ajax请求
平台提供的前端ui组件,触发事件之后,可以直接直接调用python脚本。
比如:
#点击链接 ui.link('something').on('click', context, request, 'xxx.xxx:xxxx') # 点击按钮 ui.button('submit').on('click', context, request, 'xxx.xxx:xxxx') # 输入变化 ui.input_text('name').on('change', context, request, 'xxx.xx:xxx') # 表单提交:: ui.form().on('submit', context, request, 'xxx.xxx:xxxx')
还可以直接传递参数到脚本,并保持数据类型,比如:
link.on('click', 'xxx.xxx:xx', context, request, aa=1, bb=True, cc=['aa', 1], dd=[1, 2, True], ee={'a':1, 'b':True, 'c':'hello'})
和浏览器直接访问一样:
- 脚本内可以使用context、request、view等变量(具体解释见后)
- 会检查是否有权限调用
2 作为函数调用
脚本可在其他脚本或者表达式中调用。
2.1 同步调用
作为一个函数,可以被其他脚本调用:
result = root.call_script('zopen.xxx:ass', aaa=233, bbb=123)
在脚本中调用脚本,可直接使用传入的参数,另外还可以访问 root 变量。 和浏览器调用不同:
不能直接context, request,view等变量,不能直接使用,需要额外传入:
root.call_script('zopen.xxx:xxx', context=context, request=request, view=view)
脚本的渲染模板不再起作用
脚本的权限也不再起作用
2.2 异步调用
对于耗时比较长的工作(如发送邮件、文件格式转换、文件上传、下载),可以异步调用脚本,在后台队列中运行:
root.call_script_async('zopen.xxx:ass', aaa=233, bbb=123)
注意:
异步调用对参数类型有要求, 只能传递可以json序列化的简单参数 。
因此不能传递对象,如果是内容对象,需要先转换成uid等之后再传递。
异步运行的时候,request会使用当前用户的身份,以及当前用户的语言
任务可在后台队列中查看运行情况。默认占用custom2-0队列中,也可以指定在其他队列中,方法为:
root.call_script_async('zopen.xx:xxx', ztq_queue=’custom1-0’)
异步调用如果出错,可以进行重试。10秒后重试,最多重试3次,方法为:
raise Retry(countdown=10, retries=3)
如果希望周期性永久重试,可以传递重试次数为-1:
raise Retry(countdown=10, retries=-1)
3 内置异常
- Unauthorized
- 没有权限
- LogicError
- 友好的提示用户错误信息
4 内置变量
4.1 root 站点根对象
所有脚本都可以使用这个对象,具体的接口,内容库中 有介绍
4.2 ui 组件
ui是前端组件,具体参看 《前端开发》
4.3 web调用的运行环境
这个调用是从web发起的,会有如下内置变量。
4.3.1 context 上下文对象
请求地址中的上下文对象,也就是url地址中 @ 之前的对象地址
4.3.2 request请求
仅仅在web调用脚本中有这个内置变量。
客户端请求的所有信息
- request.me.id:当前登录人
- request.method: 请求的方法
- request.me.groups: 当前登录人所在的组
- request.get_token() 当前登录人的token认证信息
- request.get_client_ip: 请求发起方的IP地址
- request.form:表单信息,request.form[field_name]
- request.bodyStream:请求内容,这个是StringIO类型,可以通过 request.bodyStream.read() 读取内容。
- request['QUERY_STRING']:请求url里面的参数信息
- request.getHeader('xxx') 读取请求消息头
- reqeust.is_mobile() 是否手机浏览器访问
- request.response是当前请求的返回信息:
- request.response.setHeader('Content-Type', 'application/excel') #设置消息头
- request.response.redirect(url, trusted=True) #跳转到另外一个地址
可以 print str(request) 得到所有的请求信息
4.3.3 view 当前页面
前端引擎中的当前页面,可进行页面操作,具体参看《前端开发》
5 Python代码沙箱
处于安全考虑,系统限制使用有限的一组类库,具体如下:
5.1 语法限制
禁止使用 _ 开头的变量、函数、方法
_ 开头在Python中表示私有方法,禁止使用。
class 关键字也是限制使用的
定位为脚本级的开发,禁止使用class。
5.2 对print方法的重载
为了模拟在命令行的使用场景,我们提供print方法输出:
print(1) print(2)
注意,所有print的结果,保存在一个 printed 局部变量中,通常通过如下方法输出:
return printed
由于printed是一个局部变量,下面的代码并不能正常工作:
def aaaa(): print 1 print 2 aaaa() return printed
应该如下改写:
def aaaa(): print 1 print 2 return printed print aaaa() return printed
5.3 string.Template 的改进
如果需要定制自己的ID和分割副,可以这样:
mytemplate = string.Template.new(template, idpattern='[_a-z][_a-z0-9\.:]*', delimiter=None) result = mytemplate.safe_substitute(values)
5.4 可以使用的类库
诸如os等方法,是限制使用的
5.4.1 时间
- time
- pytz
5.4.2 数据处理
- random
- hashlib
- hmac
- re
- Crypto.Cipher
- jwt(PyJWT)
5.4.3 网络相关
- urllib
- urllib2
- xmlrpclib
- urlparse:
- imaplib
- ldap
- davlib
- cgi
- HTMLParser
- Soap协议 WSDL.Proxy
5.4.4 转换相关
- xmltodict : xml转换为dict
- binascii : 二进制转ascii
- yaml/pyaml :yaml导出 , pyaml.dump 能导出更好的yaml格式
- json : json转换,新增json.dumps2 和 json.loads2,更好支持时间类型
- chardet :字符编码检测
5.4.5 数据库访问
- cx_Oracle: oracle数据特有的驱动
- transaction :事务管理
5.4.6 已经import,可内置使用的
- datetime
- calendar
- excel文件的读写: xlwt, xlrd
- StringIO
5.4.7 访问webservice
todo
5.4.8 访问xml-rpc
todo
5.4.9 拼音处理pinyin
可以将汉字转换为拼音:
pinyin.hanzi2pinyin('我们')
可以根据拼音进行排序汉字:
pinyin.sortbypinyin(['张三', '李四', '张武'])
5.5 突破沙箱
如果你是独立部署,确信所有软件包都是安全的。 这时候,你希望能够import任意包,比如可以访问文件系统,使用ctypes等。
可以在控制台中设置 etcd:
/workonline/restrict_script_import false
一旦设置这个开关,平台的脚本将可以import所有安装的python库。