예제 #1
0
class IrQWeb(models.AbstractModel, QWeb):
    _inherit = 'ir.qweb'

    @tools.conditional(
        # in non-xml-debug mode we want assets to be cached forever, and the admin can force a cache clear
        # by restarting the server after updating the source code (or using the "Clear server cache" in debug tools)
        'xml' not in tools.config['dev_mode'],
        tools.ormcache('xmlid', 'options.get("lang", "en_US")', 'css', 'js',
                       'debug', 'async'),
    )
    def _get_asset(self,
                   xmlid,
                   options,
                   css=True,
                   js=True,
                   debug=False,
                   async=False,
                   values=None):
예제 #2
0
class IrQWeb(models.AbstractModel, QWeb):
    """ Base QWeb rendering engine
    * to customize ``t-field`` rendering, subclass ``ir.qweb.field`` and
      create new models called :samp:`ir.qweb.field.{widget}`
    Beware that if you need extensions or alterations which could be
    incompatible with other subsystems, you should create a local object
    inheriting from ``ir.qweb`` and customize that.
    """

    _name = 'ir.qweb'

    @api.model
    def render(self, id_or_xml_id, values=None, **options):
        """ render(id_or_xml_id, values, **options)

        Render the template specified by the given name.

        :param id_or_xml_id: name or etree (see get_template)
        :param dict values: template values to be used for rendering
        :param options: used to compile the template (the dict available for the rendering is frozen)
            * ``load`` (function) overrides the load method
            * ``profile`` (float) profile the rendering (use astor lib) (filter
              profile line with time ms >= profile)
        """
        for method in dir(self):
            if method.startswith('render_'):
                _logger.warning("Unused method '%s' is found in ir.qweb." %
                                method)

        context = dict(self.env.context,
                       dev_mode='qweb' in tools.config['dev_mode'])
        context.update(options)

        return super(IrQWeb, self).render(id_or_xml_id,
                                          values=values,
                                          **context)

    def default_values(self):
        """ attributes add to the values for each computed template
        """
        default = super(IrQWeb, self).default_values()
        default.update(
            request=request,
            cache_assets=round(time() / 180),
            true=True,
            false=False
        )  # true and false added for backward compatibility to remove after v10
        return default

    # assume cache will be invalidated by third party on write to ir.ui.view
    def _get_template_cache_keys(self):
        """ Return the list of context keys to use for caching ``_get_template``. """
        return [
            'lang', 'inherit_branding', 'editable', 'translatable',
            'edit_translations'
        ]

    # apply ormcache_context decorator unless in dev mode...
    @tools.conditional(
        'xml' not in tools.config['dev_mode'],
        tools.ormcache(
            'id_or_xml_id',
            'tuple(map(options.get, self._get_template_cache_keys()))'),
    )
    def compile(self, id_or_xml_id, options):
        return super(IrQWeb, self).compile(id_or_xml_id, options=options)

    def load(self, name, options):
        lang = options.get('lang', 'en_US')
        env = self.env
        if lang != env.context.get('lang'):
            env = env(context=dict(env.context, lang=lang))
        template = env['ir.ui.view'].read_template(name)

        res_id = isinstance(name, (int, long)) and name or None
        if res_id:
            for node in etree.fromstring(template):
                if node.get('t-name'):
                    return node
                elif res_id and node.tag == "t":
                    node.set('t-name', str(res_id))
                    return node

        return template

    # order

    def _directives_eval_order(self):
        directives = super(IrQWeb, self)._directives_eval_order()
        directives.insert(directives.index('call'), 'lang')
        directives.insert(directives.index('field'), 'call-assets')
        return directives

    # compile directives

    def _compile_directive_lang(self, el, options):
        lang = el.attrib.pop('t-lang', 'en_US')
        if el.get('t-call-options'):
            el.set('t-call-options',
                   el.get('t-call-options')[0:-1] + u', "lang": %s}' % lang)
        else:
            el.set('t-call-options', u'{"lang": %s}' % lang)
        return self._compile_node(el, options)

    def _compile_directive_call_assets(self, el, options):
        """ This special 't-call' tag can be used in order to aggregate/minify javascript and css assets"""
        if len(el):
            raise "t-call-assets cannot contain children nodes"

        # self._get_asset(xmlid, options, css=css, js=js, debug=values.get('debug'), async=async, values=values)
        return [
            self._append(
                ast.Call(
                    func=ast.Attribute(value=ast.Name(id='self',
                                                      ctx=ast.Load()),
                                       attr='_get_asset',
                                       ctx=ast.Load()),
                    args=[
                        ast.Str(el.get('t-call-assets')),
                        ast.Name(id='options', ctx=ast.Load()),
                    ],
                    keywords=[
                        ast.keyword('css',
                                    self._get_attr_bool(el.get('t-css',
                                                               True))),
                        ast.keyword('js',
                                    self._get_attr_bool(el.get('t-js', True))),
                        ast.keyword(
                            'debug',
                            ast.Call(func=ast.Attribute(value=ast.Name(
                                id='values', ctx=ast.Load()),
                                                        attr='get',
                                                        ctx=ast.Load()),
                                     args=[ast.Str('debug')],
                                     keywords=[],
                                     starargs=None,
                                     kwargs=None)),
                        ast.keyword(
                            'async',
                            self._get_attr_bool(el.get('async', False))),
                        ast.keyword('values',
                                    ast.Name(id='values', ctx=ast.Load())),
                    ],
                    starargs=None,
                    kwargs=None))
        ]

    # for backward compatibility to remove after v10
    def _compile_widget_options(self, el, directive_type):
        field_options = super(IrQWeb, self)._compile_widget_options(
            el, directive_type)

        if ('t-%s-options' % directive_type) in el.attrib:
            if tools.config['dev_mode']:
                _logger.warning(
                    "Use new syntax t-options instead of t-%s-options" %
                    directive_type)
            if not field_options:
                field_options = el.attrib.pop('t-%s-options' % directive_type)

        if field_options and 'monetary' in field_options:
            try:
                options = "{'widget': 'monetary'"
                for k, v in json.loads(field_options).iteritems():
                    print k, v
                    if k in ('display_currency', 'from_currency'):
                        options = "%s, '%s': %s" % (options, k, v)
                    else:
                        options = "%s, '%s': '%s'" % (options, k, v)
                options = "%s}" % options
                field_options = options
                _logger.warning(
                    "Use new syntax for '%s' monetary widget t-options (python dict instead of deprecated JSON syntax)."
                    % etree.tostring(el))
            except ValueError:
                pass

        return field_options

    # end backward

    # method called by computing code

    @tools.conditional(
        # in non-xml-debug mode we want assets to be cached forever, and the admin can force a cache clear
        # by restarting the server after updating the source code (or using the "Clear server cache" in debug tools)
        'xml' not in tools.config['dev_mode'],
        tools.ormcache('xmlid', 'options.get("lang", "en_US")', 'css', 'js',
                       'debug', 'async'),
    )
    def _get_asset(self,
                   xmlid,
                   options,
                   css=True,
                   js=True,
                   debug=False,
                   async=False,
                   values=None):