一般通过继承的形式来创建controller类,继承自odoo.http.Controller。
以route装饰器来装饰定义的方法,提供url路由访问路径:
class MyController(odoo.http.Controller)://继承controller定义控制器 @route(‘/some_url‘, auth=‘public‘)//装饰器路由访问方法,并指明访问方式:公开还是需要用户登陆 def handler(self): return stuff()
from odoo.http import request from odoo import http, tools from odoo.tools import pycompat from odoo.modules.module import get_resource_path, get_module_path logger = logging.getLogger(__name__) class Web_Editor(http.Controller): #------------------------------------------------------ # Backend snippet #------------------------------------------------------ @http.route(‘/web_editor/snippets‘, type=‘json‘, auth="user") def snippets(self, **kwargs): return request.env.ref(‘web_editor.snippets‘).render(None) #------------------------------------------------------ # Backend html field #------------------------------------------------------ @http.route(‘/web_editor/field/html‘, type=‘http‘, auth="user") def FieldTextHtml(self, model=None, res_id=None, field=None, callback=None, **kwargs): kwargs.update( model=model, res_id=res_id, field=field, datarecord=json.loads(kwargs[‘datarecord‘]), debug=request.debug) for k in kwargs: if isinstance(kwargs[k], pycompat.string_types) and kwargs[k].isdigit(): kwargs[k] = int(kwargs[k]) trans = dict( lang=kwargs.get(‘lang‘, request.env.context.get(‘lang‘)), translatable=kwargs.get(‘translatable‘), edit_translations=kwargs.get(‘edit_translations‘), editable=kwargs.get(‘enable_editor‘)) kwargs.update(trans) record = None if model and kwargs.get(‘res_id‘): record = request.env[model].with_context(trans).browse(kwargs.get(‘res_id‘)) kwargs.update(content=record and getattr(record, field) or "") return request.render(kwargs.get("template") or "web_editor.FieldTextHtml", kwargs, uid=request.uid)
odoo.http.route(route=None, **kw) 装饰器可以将对应方法装饰为处理对应的http请求。
装饰器参数有:
字符串或数组,决定哪些http请求可以匹配所装饰的方法,可以是单个字符串、或多个字符串的数组。
request请求的类型,可以是http或json。
认证方法的类型,可以是以下几种:
user - 必须是已通过登录认证的用户,才能访问该请求。如果未经过登录直接访问,则会拦截并跳转回odoo登录页面。
public - 使用公用的认证,可以不经过登录验证直接访问。
none - 相应的方法总是可用,一般用于框架和认证模块,对应请求没有办法访问数据库或指向数据库的设置。
这个请求所应用的一系列http方法【PATCH, POST, PUT, 或者DELETE】,如果没指定则是所有方法。
methods=[‘POST‘, ‘GET‘]
跨域资源cors参数。
是否开启CSRF跨域保护,默认True。
a)如果表单是用python代码生成的,可通过request.csrf_token() 获取csrf
b)如果表单是用javascript生成的,CSRF token会自动被添加到QWEB环境变量中,通过require(‘web.core‘).csrf_token获取
c)如果终端可从其他地方以api或webhook形式调用,需要将对应的csrf禁用,此时最好用其他方式进行验证
#------------------------------------------------------ # add attachment (images or link) #------------------------------------------------------ @http.route(‘/web_editor/attachment/add‘, type=‘http‘, auth=‘user‘, methods=[‘POST‘], website=True) def attach(self, upload=None, url=None, disable_optimization=None, filters=None, **kwargs): # the upload argument doesn‘t allow us to access the files if more than # one file is uploaded, as upload references the first file # therefore we have to recover the files from the request object Attachments = request.env[‘ir.attachment‘] # registry for the attachment table res_model = kwargs.get(‘res_model‘, ‘ir.ui.view‘) if res_model != ‘ir.ui.view‘ and kwargs.get(‘res_id‘): res_id = int(kwargs[‘res_id‘]) else: res_id = None uploads = [] message = None if not upload: # no image provided, storing the link and the image name name = url.split("/").pop() # recover filename datas_fname = name if filters: datas_fname = filters + ‘_‘ + datas_fname attachment = Attachments.create({ ‘name‘: name, ‘datas_fname‘: datas_fname, ‘type‘: ‘url‘, ‘url‘: url, ‘public‘: res_model == ‘ir.ui.view‘, ‘res_id‘: res_id, ‘res_model‘: res_model, }) attachment.generate_access_token() uploads += attachment.read([‘name‘, ‘mimetype‘, ‘checksum‘, ‘url‘, ‘res_id‘, ‘res_model‘, ‘access_token‘]) else: # images provided try: attachments = request.env[‘ir.attachment‘] for c_file in request.httprequest.files.getlist(‘upload‘): data = c_file.read() try: image = Image.open(io.BytesIO(data)) w, h = image.size if w*h > 42e6: # Nokia Lumia 1020 photo resolution raise ValueError( u"Image size excessive, uploaded images must be smaller " u"than 42 million pixel") if not disable_optimization and image.format in (‘PNG‘, ‘JPEG‘): data = tools.image_save_for_web(image) except IOError as e: pass name = c_file.filename datas_fname = name if filters: datas_fname = filters + ‘_‘ + datas_fname attachment = Attachments.create({ ‘name‘: name, ‘datas‘: base64.b64encode(data), ‘datas_fname‘: datas_fname, ‘public‘: res_model == ‘ir.ui.view‘, ‘res_id‘: res_id, ‘res_model‘: res_model, }) attachment.generate_access_token() attachments += attachment uploads += attachments.read([‘name‘, ‘mimetype‘, ‘checksum‘, ‘url‘, ‘res_id‘, ‘res_model‘, ‘access_token‘]) except Exception as e: logger.exception("Failed to upload image to attachment") message = pycompat.text_type(e) return """<script type=‘text/javascript‘> window.attachments = %s; window.error = %s; </script>""" % (json.dumps(uploads), json.dumps(message))
请求对象在收到请求时自动设置到odoo.http.request,可以通过该对象提前request中携带的 参数、cookie、session对象等。
1)httprequest
原始的werkzeug.wrappers.Request对象
2)params
请求参数的映射
3)cr
当前方法调用的初始游标,当使用none的认证方式时读取游标会报错
4)context
当前请求的上下文键值映射
5)env
绑定到当前请求的环境
6)session
储存当前请求session数据的OpenERPSession
7)debug
指定当前请求是否是debug模式
8)db
当前请求所关联的数据库,当使用none认证时为None
9)csrf_token(time_limit=3600)
为该请求生成并返回一个token(参数以秒计算,默认1小时,如果传None表示与当前用户session时间相同)
用于处理http类型请求的函数,匹配 路由参数、查询参数、表格参数,如果有指定文件也会传给该方法。为防止重名,路由参数优先级最高。
该函数的返回值有三种:
用于生成没有HTML的响应 或 自定义响应头、cookie的html响应。
由于处理函数只以字符串形式返回html标记内容,需要组成一个完整的响应对象,这样客户端才能解析
参数有:
1)data (basestring)
响应主体。
2)headers ([(name, value)])
http响应头。
3)cookies (collections.Mapping)
发送给客户端的cookie。
给出404 NOT FOUND响应。
渲染qweb模板,在调度完成后会对给定的模板进行渲染并返回给客户端。
参数有:
1)template (basestring)
用于渲染的模板完整ID:模块.模版
2)qcontext (dict)
用于渲染的上下文环境。
3)lazy (bool)
渲染动作是否应该拖延到最后执行。
4)kw
转发到werkzeug响应对象。
处理通过http发来的json rpc请求。
参数:params -- 是一个json格式对象
返回值:一个json-rpc格式的,以JSON-RPC Response对象的组装。
响应对象通过控制器的路由传递,在werkzeug.wrappers.Response之外,该类的构造方法会添加以下参数到qweb的渲染中:
1)template (basestring)
用于渲染的模板。
2)qcontext (dict)
用在渲染中的上下文环境。
3)uid (int)
用于调用ir.ui.view渲染的用户id,None时使用当前请求的id。
上面的参数在实际渲染之前可以随时作为Response对象的属性进行修改。
def json_rpc(url, method, params): data = { "jsonrpc": "2.0", "method": method, "params": params, "id": random.randint(0, 1000000000), } req = urllib.request.Request(url=url, data=json.dumps(data), headers={"Content-Type":"application/json"}) reply = json.loads(urllib.request.urlopen(req).read().decode(‘UTF-8‘)) if reply.get("error"): raise Exception(reply["error"]) return reply["result"]
response对象可以调用以下方法:
render() - 渲染响应对象的模板,并返回内容。
flatten() - 强制渲染响应对象的模板,将结果设置为响应主体,并将模板复原。
本文来源:https://blog.csdn.net/jehuyang/article/details/90770507
原文:https://www.cnblogs.com/1314520xh/p/12398565.html