zoukankan      html  css  js  c++  java
  • odoo中Controller

     

    一:Controller

        一般通过继承的形式来创建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请求。

        装饰器参数有:

    1)route

        字符串或数组,决定哪些http请求可以匹配所装饰的方法,可以是单个字符串、或多个字符串的数组。

    2)type

        request请求的类型,可以是http或json。

    3)auth

        认证方法的类型,可以是以下几种:

            user - 必须是已通过登录认证的用户,才能访问该请求。如果未经过登录直接访问,则会拦截并跳转回odoo登录页面。

            public - 使用公用的认证,可以不经过登录验证直接访问。

            none - 相应的方法总是可用,一般用于框架和认证模块,对应请求没有办法访问数据库或指向数据库的设置。

    4)methods

        这个请求所应用的一系列http方法【PATCH, POST, PUT, 或者DELETE】,如果没指定则是所有方法。

     methods=['POST', 'GET']

    5)cors

        跨域资源cors参数。

    6)csrf(boolean)

        是否开启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:class odoo.http.WebRequest(httprequest)

     所有odoo WEB请求的父类,一般用于进行请求对象的初始化,其构建函数的参数有:

        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时间相同)

    2:class odoo.http.HttpRequest(*args)

        用于处理http类型请求的函数,匹配 路由参数、查询参数、表格参数,如果有指定文件也会传给该方法。为防止重名,路由参数优先级最高。
        该函数的返回值有三种:

      • 无效值,HTTP响应会返回一个204(没有内容)
      • 一个werkzeug 响应对象
      • 一个字符串或unicode,会被响应对象包装并使用HTML解析

        3:make_response(data, headers=None, cookies=None)

        用于生成没有HTML的响应 或 自定义响应头、cookie的html响应。
        由于处理函数只以字符串形式返回html标记内容,需要组成一个完整的响应对象,这样客户端才能解析

        参数有:

        1)data (basestring)

        响应主体。

        2)headers ([(name, value)])

        http响应头。

        3)cookies (collections.Mapping)

        发送给客户端的cookie。

        4:not_found(description=None)

        给出404 NOT FOUND响应。

        5:render(template, qcontext=None, lazy=True, **kw)

        渲染qweb模板,在调度完成后会对给定的模板进行渲染并返回给客户端。

        参数有:

        1)template (basestring)

        用于渲染的模板完整ID:模块.模版

        2)qcontext (dict)

        用于渲染的上下文环境。

        3)lazy (bool)

       渲染动作是否应该拖延到最后执行。

        4)kw

        转发到werkzeug响应对象。

        6:class odoo.http.JsonRequest(*args)

        处理通过http发来的json rpc请求。

        参数:params -- 是一个json格式对象

        返回值:一个json-rpc格式的,以JSON-RPC Response对象的组装。

    四:响应相关

      1:class odoo.http.Response(args, *kw)

        响应对象通过控制器的路由传递,在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

  • 相关阅读:
    NOIP 2012 T5 借教室 [洛谷P1083]
    POJ2437 Muddy roads
    POJ2288 Islands and Bridges
    洛谷P2014 TYVJ1051 选课
    POJ1741 Tree
    CODEVS1995 || TYVJ1863 黑魔法师之门
    TYVJ1939 玉蟾宫
    TYVJ1305 最大子序和
    POJ1737 Connected Graph
    TYVJ1864 守卫者的挑战
  • 原文地址:https://www.cnblogs.com/1314520xh/p/12398565.html
Copyright © 2011-2022 走看看