Python 如何从android应用程序连接到Odoo数据库
我正在开发一个Android应用程序,我想从Odoo服务器检索数据 为此,我在Odoo中开发了一个自定义模块,在其中我创建了一个控制器 我的控制器: 当我使用Python 如何从android应用程序连接到Odoo数据库,python,json,python-3.x,odoo,odoo-11,Python,Json,Python 3.x,Odoo,Odoo 11,我正在开发一个Android应用程序,我想从Odoo服务器检索数据 为此,我在Odoo中开发了一个自定义模块,在其中我创建了一个控制器 我的控制器: 当我使用auth='public'时,此函数工作正常,但当我使用auth='user'时,我得到以下json响应: 答复[200] { u'jsonrpc': u'2.0', u'id': None, u'error': { u'message': u'Odoo Session Expir
auth='public'
时,此函数工作正常,但当我使用auth='user'
时,我得到以下json响应:
答复[200]
{
u'jsonrpc': u'2.0',
u'id': None,
u'error': {
u'message': u'Odoo Session Expired',
u'code': 100,
u'data': {
u'debug': u'Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/odoo/http.py", line 650, in _handle_exception
return super(JsonRequest, self)._handle_exception(exception)
File "/usr/lib/python3/dist-packages/odoo/http.py", line 310, in _handle_exception
raise pycompat.reraise(type(exception), exception, sys.exc_info()[2])
File "/usr/lib/python3/dist-packages/odoo/tools/pycompat.py", line 87, in reraise
raise value
File "/usr/lib/python3/dist-packages/odoo/addons/http_routing/models/ir_http.py", line 342, in _dispatch
cls._authenticate(func.routing[\'auth\'])
File "/usr/lib/python3/dist-packages/odoo/addons/base/ir/ir_http.py", line 117, in _authenticate
getattr(cls, "_auth_method_%s" % auth_method)()
File "/usr/lib/python3/dist-packages/odoo/addons/base/ir/ir_http.py", line 90, in _auth_method_user
raise http.SessionExpiredException("Session expired")
odoo.http.SessionExpiredException: Session expired',
u'exception_type': u'internal_error',
u'message': u'Session expired',
u'name': u'odoo.http.SessionExpiredException',
u'arguments': [u'Session expired']
}
}
}
我的工作基于,这是一份官方的奥多文件,但问题如下:
1它要求我在每个函数中写入管理员密码,这似乎很危险
2身份验证后,我获得了我的用户id,但没有会话令牌。那么,如何使用auth='user'
通知我的函数我已连接到哪个用户
下面是我测试调用的脚本:
import requests
import json
url_connect = "<my url>/user/login"
url = "<my url>/user/getInfo"
headers = {'Content-Type': 'application/json'}
data_connect = {
"params": {
"email": "<my test account email>",
"password": "<my test account password>",
}
}
data = {
"params": {
"token": <my test account id>,
}
}
data_json = json.dumps(data)
r = requests.get(url=url_connect, data=json.dumps(data_connect), headers=headers)
print(r)
print(r.json())
r = requests.get(url=url, data=data_json, headers=headers)
print(r)
print(r.json())
导入请求
导入json
url_connect=“/user/login”
url=“/user/getInfo”
headers={'Content-Type':'application/json'}
数据连接={
“参数”:{
“电子邮件”:“,
“密码”:“,
}
}
数据={
“参数”:{
“代币”:,
}
}
data_json=json.dumps(数据)
r=requests.get(url=url\u connect,data=json.dumps(data\u connect),headers=headers)
印刷品(r)
打印(r.json())
r=requests.get(url=url,data=data\u json,headers=headers)
印刷品(r)
打印(r.json())
需要注意的事项:
- 从不在GET请求中发送凭据
- 所有Odoo RPC请求都是POST请求
- 如果使用/web/session/authenticate
- 外部API拟在odoo框架之外使用。开发模块时,如果在模型中,则使用self.env['
'],如果在控制器中,则使用http.request.env[' '] - 调用/web/session/authenticate返回一个包含会话id的json,您必须在cookies中将其传递给后续请求,直到调用/web/session/destroy注销
import requests
import json
url_connect = "http://localhost:8069/web/session/authenticate"
url = "http://localhost:8069/web/session/get_session_info"
headers = {'Content-Type': 'application/json'}
data_connect = {
"params": {
"db": "demo1",
"login": "admin",
"password": "admin",
}
}
data = {}
session = requests.Session()
r = session.post(url=url_connect, data=json.dumps(data_connect), headers=headers)
if r.ok:
result = r.json()['result']
if result.get('session_id'):
session.cookies['session_id'] = result.get('session_id')
r = session.post(url=url, data=json.dumps(data), headers=headers)
print(r)
print(r.json())
要从控制器获取信息,您可以使用request.env.user,它目前保存已登录的用户,并且由于您指定了auth='user',因此它必须是有效的。示例代码可能如下所示:
from odoo.http import request
class UserController(http.Controller):
@http.route('/user/getInfo', type='json', method='POST', auth='user')
def get_info(self, **kwargs):
current_user = request.env.user
Response.status = '200 Succesful operation'
json_result = {'info': current_user.info}
return json.dumps(json_result)
写得很好,你已经做了家庭作业。这对我来说非常有用,可以使用api样式的请求对移动用户会话进行身份验证
@http.route([
'/m/login/email',
], type='http', auth="public", website=True, methods=["POST"], csrf=False)
def users_login_email(self, **kwargs):
if kwargs:
data = json.loads(kwargs.keys()[0])
else:
data = json.loads(request.httprequest.data)
email = data.get('email')
password = data.get('password')
if not request.session.db:
setup_db()
uid = request.session.authenticate(request.session.db, email, password)
if uid:
return self._user_details(uid)
body = json.dumps({"body": ["Credenciales Incorrectas"]})
return werkzeug.wrappers.Response(body, status=403, headers=[
('Content-Type', 'application/json'), ('Content-Length', len(body))
])
另外,我没有使用auth='user'
来防止Odoo干扰重定向和web内容检查。我在需要经过身份验证的用户返回正确的HTTP错误状态代码的控制器路由中使用此注释包装器
def check_user(f):
@functools.wraps(f)
def wrap(*args, **kwargs):
if not request.session.db:
setup_db()
request.uid = request.session.uid
if not request.uid:
body = json.dumps({"body": ["Session Expired"]})
return werkzeug.wrappers.Response(body, status=403, headers=[
('Content-Type', 'application/json'), ('Content-Length', len(body))
])
return f(*args, **kwargs)
return wrap
您可以这样使用它:
@check_user
@http.route([
'/m/<int:shop_id>/cart/info',
], type='http', auth="public", website=True)
def cart_info(self, shop_id, **kwargs):
@check\u用户
@http.route([
“/m//cart/info”,
],type='http',auth=“public”,website=True)
def购物车信息(自身、店铺id、**kwargs):
我还尝试使用“/web/session/authenticate”进行连接,这是odoo的内置控制器。它工作正常,并返回会话ID。但是我如何使用这个会话ID呢?我试图将它传递到我的参数中,但效果并不好,我仍然有相同的答案“Odoo会话已过期”“”,感谢没有基本Odoo http重定向的解决方案。这可能会成为一个问题,如果是这样,我会尝试你的解决方案。
def check_user(f):
@functools.wraps(f)
def wrap(*args, **kwargs):
if not request.session.db:
setup_db()
request.uid = request.session.uid
if not request.uid:
body = json.dumps({"body": ["Session Expired"]})
return werkzeug.wrappers.Response(body, status=403, headers=[
('Content-Type', 'application/json'), ('Content-Length', len(body))
])
return f(*args, **kwargs)
return wrap
@check_user
@http.route([
'/m/<int:shop_id>/cart/info',
], type='http', auth="public", website=True)
def cart_info(self, shop_id, **kwargs):