def value_to_html(self, value, options): display_currency = options['display_currency'] if not isinstance(value, (int, float)): raise ValueError( _("The value send to monetary field is not a number.")) # lang.format mandates a sprintf-style format. These formats are non- # minimal (they have a default fixed precision instead), and # lang.format will not set one by default. currency.round will not # provide one either. So we need to generate a precision value # (integer > 0) from the currency's rounding (a float generally < 1.0). fmt = "%.{0}f".format(display_currency.decimal_places) if options.get('from_currency'): date = options.get('date') or fields.Date.today() company_id = options.get('company_id') if company_id: company = self.env['res.company'].browse(company_id) else: company = self.env.company value = options['from_currency']._convert(value, display_currency, company, date) lang = self.user_lang() formatted_amount = lang.format( fmt, display_currency.round(value), grouping=True, monetary=True).replace(r' ', '\N{NO-BREAK SPACE}').replace( r'-', '-\N{ZERO WIDTH NO-BREAK SPACE}') pre = post = '' if display_currency.position == 'before': pre = '{symbol}\N{NO-BREAK SPACE}'.format( symbol=display_currency.symbol or '') else: post = '\N{NO-BREAK SPACE}{symbol}'.format( symbol=display_currency.symbol or '') if options.get( 'label_price') and lang.decimal_point in formatted_amount: sep = lang.decimal_point integer_part, decimal_part = formatted_amount.split(sep) integer_part += sep return M( '{pre}<span class="oe_currency_value">{0}</span><span class="oe_currency_value" style="font-size:0.5em">{1}</span>{post}' ).format(integer_part, decimal_part, pre=pre, post=post) return M( '{pre}<span class="oe_currency_value">{0}</span>{post}').format( formatted_amount, pre=pre, post=post)
def nl2br(string): """ Converts newlines to HTML linebreaks in ``string``. returns the unicode result :param str string: :rtype: unicode """ return pycompat.to_text(string).replace('\n', M('<br>\n'))
def value_to_html(self, value, options): try: # FIXME: maaaaaybe it could also take raw bytes? image = Image.open(BytesIO(base64.b64decode(value))) image.verify() except IOError: raise ValueError("Non-image binary fields can not be converted to HTML") except: # image.verify() throws "suitable exceptions", I have no idea what they are raise ValueError("Invalid image content") return M('<img src="data:%s;base64,%s">' % (Image.MIME[image.format], value.decode('ascii')))
def record_to_html(self, record, field_name, options): assert options['tagName'] != 'img',\ "Oddly enough, the root tag of an image field can not be img. " \ "That is because the image goes into the tag, or it gets the " \ "hose again." if options.get('qweb_img_raw_data', False): return super(Image, self).record_to_html(record, field_name, options) aclasses = ['img', 'img-fluid'] if options.get('qweb_img_responsive', True) else ['img'] aclasses += options.get('class', '').split() classes = ' '.join(map(escape, aclasses)) src, src_zoom = self._get_src_urls(record, field_name, options) if options.get('alt-field') and getattr(record, options['alt-field'], None): alt = escape(record[options['alt-field']]) elif options.get('alt'): alt = options['alt'] else: alt = escape(record.display_name) itemprop = None if options.get('itemprop'): itemprop = options['itemprop'] atts = OrderedDict() atts["src"] = src atts["itemprop"] = itemprop atts["class"] = classes atts["style"] = options.get('style') atts["alt"] = alt atts["data-zoom"] = src_zoom and u'1' or None atts["data-zoom-image"] = src_zoom atts["data-no-post-process"] = options.get('data-no-post-process') atts = self.env['ir.qweb']._post_processing_att( 'img', atts, options.get('template_options')) img = ['<img'] for name, value in atts.items(): if value: img.append(' ') img.append(escape(pycompat.to_text(name))) img.append('="') img.append(escape(pycompat.to_text(value))) img.append('"') img.append('/>') return M(''.join(img))
def value_to_html(self, value, options): irQweb = self.env['ir.qweb'] # wrap value inside a body and parse it as HTML body = etree.fromstring("<body>%s</body>" % value, etree.HTMLParser(encoding='utf-8'))[0] # use pos processing for all nodes with attributes for element in body.iter(): if element.attrib: attrib = dict(element.attrib) attrib = irQweb._post_processing_att(element.tag, attrib, options.get('template_options')) element.attrib.clear() element.attrib.update(attrib) return M(etree.tostring(body, encoding='unicode', method='html')[6:-7])
def value_to_html(self, value, options=None): if not value: return '' barcode_symbology = options.get('symbology', 'Code128') barcode = self.env['ir.actions.report'].barcode( barcode_symbology, value, **{key: value for key, value in options.items() if key in ['width', 'height', 'humanreadable', 'quiet', 'mask']}) img_element = html.Element('img') for k, v in options.items(): if k.startswith('img_') and k[4:] in safe_attrs: img_element.set(k[4:], v) if not img_element.get('alt'): img_element.set('alt', _('Barcode %s') % value) img_element.set('src', 'data:image/png;base64,%s' % base64.b64encode(barcode).decode()) return M(html.tostring(img_element, encoding='unicode'))
def value_to_html(self, value, options): if not value: return '' opf = options.get('fields') or [ "name", "address", "phone", "mobile", "email" ] sep = options.get('separator') template_options = options.get('template_options', {}) if sep: opsep = escape(sep) elif template_options.get('no_tag_br'): # escaped joiners will auto-escape joined params opsep = escape(', ') else: opsep = M('<br/>') value = value.sudo().with_context(show_address=True) name_get = value.name_get()[0][1] # Avoid having something like: # name_get = 'Foo\n \n' -> This is a res.partner with a name and no address # That would return markup('<br/>') as address. But there is no address set. if any(elem.strip() for elem in name_get.split("\n")[1:]): address = opsep.join(name_get.split("\n")[1:]).strip() else: address = '' val = { 'name': name_get.split("\n")[0], 'address': address, 'phone': value.phone, 'mobile': value.mobile, 'city': value.city, 'country_id': value.country_id.display_name, 'website': value.website, 'email': value.email, 'vat': value.vat, 'vat_label': value.country_id.vat_label or _('VAT'), 'fields': opf, 'object': value, 'options': options } return self.env['ir.qweb']._render('base.contact', val, **template_options)
def value_to_html(self, value, options): if not value: return '' opf = options.get('fields') or [ "name", "address", "phone", "mobile", "email" ] sep = options.get('separator') template_options = options.get('template_options', {}) if sep: opsep = escape(sep) elif template_options.get('no_tag_br'): # escaped joiners will auto-escape joined params opsep = escape(', ') else: opsep = M('<br/>') value = value.sudo().with_context(show_address=True) name_get = value.name_get()[0][1] val = { 'name': name_get.split("\n")[0], 'address': opsep.join(name_get.split("\n")[1:]).strip(), 'phone': value.phone, 'mobile': value.mobile, 'city': value.city, 'country_id': value.country_id.display_name, 'website': value.website, 'email': value.email, 'vat': value.vat, 'vat_label': value.country_id.vat_label or _('VAT'), 'fields': opf, 'object': value, 'options': options } return self.env['ir.qweb']._render('base.contact', val, **template_options)
def value_to_html(self, value, options): return M('<img src="%s">' % (value))
def l20n(tid, **kwargs): data = tojson(kwargs) if kwargs else None return M(_L20N_TEMPLATE.render(tid=tid, data=data))