[FIX] move conversion code from ir.fields.converter into website.qweb structures
bzr revid: xmo@openerp.com-20131009133112-05dglhptiw019838
This commit is contained in:
parent
a3f7cfd669
commit
eaef36c910
|
@ -1,6 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import ir_fields
|
||||
import view
|
||||
import website
|
||||
import ir_qweb
|
||||
|
||||
import test_models
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from lxml import etree, html
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools import ustr
|
||||
|
||||
class converter(orm.Model):
|
||||
_inherit = 'ir.fields.converter'
|
||||
|
||||
def _html_to_integer(self, cr, uid, model, column, value, context=None):
|
||||
return int(value.text_content().strip()), []
|
||||
|
||||
def _html_to_float(self, cr, uid, model, column, value, context=None):
|
||||
return float(value.text_content().strip()), []
|
||||
|
||||
def _html_to_passthrough(self, cr, uid, model, column, value, context=None):
|
||||
return value.text_content().strip(), []
|
||||
|
||||
_html_to_char = _html_to_date = _html_to_datetime = _html_to_passthrough
|
||||
|
||||
def _html_to_text(self, cr, uid, model, column, value, context=None):
|
||||
return value.text_content(), []
|
||||
|
||||
def _html_to_selection(self, cr, uid, model, column, value, context=None):
|
||||
text = value.text_content().strip()
|
||||
|
||||
selection = column.reify(cr, uid, model, column, context=context)
|
||||
for k, v in selection:
|
||||
if isinstance(v, str):
|
||||
v = ustr(v)
|
||||
if text == v:
|
||||
return k, []
|
||||
|
||||
warning = u"No value found for label %s in selection %s" % (text, selection)
|
||||
# FIXME: ?
|
||||
return False, [Warning(warning.encode('utf-8'))]
|
||||
|
||||
def _html_to_many2one(self, cr, uid, model, column, value, context=None):
|
||||
matches = self.pool[column._obj].name_search(
|
||||
cr, uid, name=value.text_content().strip(), context=context)
|
||||
# FIXME: more than one match, error reporting
|
||||
return matches[0][0], []
|
||||
|
||||
def _html_to_html(self, cr, uid, model, column, value, context=None):
|
||||
content = []
|
||||
if value.text: content.append(value.text)
|
||||
content.extend(html.tostring(child)
|
||||
for child in value.iterchildren(tag=etree.Element))
|
||||
return '\n'.join(content), []
|
||||
|
||||
|
||||
class test_converter(orm.Model):
|
||||
_name = 'website.converter.test'
|
||||
|
||||
_columns = {
|
||||
'char': fields.char(),
|
||||
'integer': fields.integer(),
|
||||
'float': fields.float(),
|
||||
'numeric': fields.float(digits=(16, 2)),
|
||||
'many2one': fields.many2one('website.converter.test.sub'),
|
||||
'binary': fields.binary(),
|
||||
'date': fields.date(),
|
||||
'datetime': fields.datetime(),
|
||||
'selection': fields.selection([
|
||||
(1, "réponse A"),
|
||||
(2, "réponse B"),
|
||||
(3, "réponse C"),
|
||||
(4, "réponse D"),
|
||||
]),
|
||||
'selection_str': fields.selection([
|
||||
('A', "Qu'il n'est pas arrivé à Toronto"),
|
||||
('B', "Qu'il était supposé arriver à Toronto"),
|
||||
('C', "Qu'est-ce qu'il fout ce maudit pancake, tabernacle ?"),
|
||||
('D', "La réponse D"),
|
||||
], string="Lorsqu'un pancake prend l'avion à destination de Toronto et "
|
||||
"qu'il fait une escale technique à St Claude, on dit:"),
|
||||
'html': fields.html(),
|
||||
'text': fields.text(),
|
||||
}
|
||||
|
||||
|
||||
class test_converter_sub(orm.Model):
|
||||
_name = 'website.converter.test.sub'
|
||||
|
||||
_columns = {
|
||||
'name': fields.char(),
|
||||
}
|
|
@ -9,8 +9,10 @@ Also, adds methods to convert values back to openerp models.
|
|||
import itertools
|
||||
|
||||
import werkzeug.utils
|
||||
from lxml import etree, html
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools import ustr
|
||||
|
||||
class QWeb(orm.AbstractModel):
|
||||
""" QWeb object for rendering stuff in the website context
|
||||
|
@ -37,26 +39,71 @@ class Field(orm.AbstractModel):
|
|||
[('data-oe-translate', 1 if column.translate else 0)]
|
||||
)
|
||||
|
||||
def value_from_string(self, value):
|
||||
return value
|
||||
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
return self.value_from_string(element.text_content().strip())
|
||||
|
||||
class Integer(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.integer'
|
||||
_inherit = ['website.qweb.field']
|
||||
|
||||
value_from_string = int
|
||||
|
||||
class Float(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.float'
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.float']
|
||||
|
||||
value_from_string = float
|
||||
|
||||
class Text(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.text'
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.text']
|
||||
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
return element.text_content()
|
||||
|
||||
class Selection(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.selection'
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.selection']
|
||||
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
value = element.text_content().strip()
|
||||
selection = column.reify(cr, uid, model, column, context=context)
|
||||
for k, v in selection:
|
||||
if isinstance(v, str):
|
||||
v = ustr(v)
|
||||
if value == v:
|
||||
return k
|
||||
|
||||
raise ValueError(u"No value found for label %s in selection %s" % (
|
||||
value, selection))
|
||||
|
||||
class ManyToOne(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.many2one'
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.many2one']
|
||||
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
# FIXME: this behavior is really weird, what if the user wanted to edit the name of the related thingy? Should m2os really be editable without a widget?
|
||||
matches = self.pool[column._obj].name_search(
|
||||
cr, uid, name=element.text_content().strip(), context=context)
|
||||
# FIXME: no match? More than 1 match?
|
||||
assert len(matches) == 1
|
||||
return matches[0][0]
|
||||
|
||||
class HTML(orm.AbstractModel):
|
||||
_name = 'website.qweb.field.html'
|
||||
_inherit = ['website.qweb.field', 'ir.qweb.field.html']
|
||||
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
content = []
|
||||
if element.text: content.append(element.text)
|
||||
content.extend(html.tostring(child)
|
||||
for child in element.iterchildren(tag=etree.Element))
|
||||
return '\n'.join(content)
|
||||
|
||||
|
||||
class Image(orm.AbstractModel):
|
||||
"""
|
||||
Widget options:
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from openerp.osv import orm, fields
|
||||
|
||||
class test_converter(orm.Model):
|
||||
_name = 'website.converter.test'
|
||||
|
||||
_columns = {
|
||||
'char': fields.char(),
|
||||
'integer': fields.integer(),
|
||||
'float': fields.float(),
|
||||
'numeric': fields.float(digits=(16, 2)),
|
||||
'many2one': fields.many2one('website.converter.test.sub'),
|
||||
'binary': fields.binary(),
|
||||
'date': fields.date(),
|
||||
'datetime': fields.datetime(),
|
||||
'selection': fields.selection([
|
||||
(1, "réponse A"),
|
||||
(2, "réponse B"),
|
||||
(3, "réponse C"),
|
||||
(4, "réponse D"),
|
||||
]),
|
||||
'selection_str': fields.selection([
|
||||
('A', "Qu'il n'est pas arrivé à Toronto"),
|
||||
('B', "Qu'il était supposé arriver à Toronto"),
|
||||
('C', "Qu'est-ce qu'il fout ce maudit pancake, tabernacle ?"),
|
||||
('D', "La réponse D"),
|
||||
], string="Lorsqu'un pancake prend l'avion à destination de Toronto et "
|
||||
"qu'il fait une escale technique à St Claude, on dit:"),
|
||||
'html': fields.html(),
|
||||
'text': fields.text(),
|
||||
}
|
||||
|
||||
|
||||
class test_converter_sub(orm.Model):
|
||||
_name = 'website.converter.test.sub'
|
||||
|
||||
_columns = {
|
||||
'name': fields.char(),
|
||||
}
|
|
@ -60,11 +60,9 @@ class view(osv.osv):
|
|||
field = el.get('data-oe-field')
|
||||
|
||||
column = Model._all_columns[field].column
|
||||
convert = self.pool['ir.fields.converter'].to_field(
|
||||
cr, uid, Model, column, fromtype="html", context=context)
|
||||
value, warnings = convert(el)
|
||||
# FIXME: report error
|
||||
if warnings: return
|
||||
converter = self.pool['website.qweb'].get_converter_for(
|
||||
el.get('data-oe-type'))
|
||||
value = converter.from_html(cr, uid, Model, column, el)
|
||||
|
||||
Model.write(cr, uid, [int(el.get('data-oe-id'))], {
|
||||
field: value
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from collections import namedtuple
|
||||
from functools import partial
|
||||
from xml.dom.minidom import getDOMImplementation
|
||||
|
||||
|
@ -10,19 +9,10 @@ from openerp.tests import common
|
|||
impl = getDOMImplementation()
|
||||
document = impl.createDocument(None, None, None)
|
||||
|
||||
Request = namedtuple('Request', 'cr uid registry')
|
||||
class RegistryProxy(object):
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
def __getitem__(self, name):
|
||||
return self.func(name)
|
||||
|
||||
class TestConvertBack(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestConvertBack, self).setUp()
|
||||
|
||||
self.Converter = self.registry('ir.fields.converter')
|
||||
|
||||
def field_rountrip_result(self, field, value, expected):
|
||||
model = 'website.converter.test'
|
||||
Model = self.registry(model)
|
||||
|
@ -36,7 +26,7 @@ class TestConvertBack(common.TransactionCase):
|
|||
field_value = 'record.%s' % field
|
||||
e.setAttribute('t-field', field_value)
|
||||
|
||||
rendered = self.registry('ir.qweb').render_tag_field(
|
||||
rendered = self.registry('website.qweb').render_tag_field(
|
||||
e, {'field': field_value}, '', {
|
||||
'record': record,
|
||||
})
|
||||
|
@ -44,12 +34,11 @@ class TestConvertBack(common.TransactionCase):
|
|||
rendered, parser=html.HTMLParser(encoding='utf-8'))
|
||||
|
||||
column = Model._all_columns[field].column
|
||||
converter = self.registry('website.qweb').get_converter_for(
|
||||
element.get('data-oe-type'))
|
||||
|
||||
from_html = self.Converter.to_field(
|
||||
self.cr, self.uid, model, column, 'html')
|
||||
|
||||
value_back, warnings = from_html(element)
|
||||
self.assertEqual(warnings, [])
|
||||
value_back = converter.from_html(
|
||||
self.cr, self.uid, model, column, element)
|
||||
|
||||
if isinstance(expected, str):
|
||||
expected = expected.decode('utf-8')
|
||||
|
|
|
@ -31,8 +31,8 @@ class TestViewSaving(common.TransactionCase):
|
|||
h.H3("Column 2"),
|
||||
h.UL(
|
||||
h.LI("Item 1"),
|
||||
h.LI(h.SPAN("My Company", attrs(model='res.company', id=1, field='name'))),
|
||||
h.LI(h.SPAN("+00 00 000 00 0 000", attrs(model='res.company', id=1, field='phone')))
|
||||
h.LI(h.SPAN("My Company", attrs(model='res.company', id=1, field='name', type='char'))),
|
||||
h.LI(h.SPAN("+00 00 000 00 0 000", attrs(model='res.company', id=1, field='phone', type='char')))
|
||||
))
|
||||
)
|
||||
self.view_id = self.registry('ir.ui.view').create(self.cr, self.uid, {
|
||||
|
@ -46,14 +46,15 @@ class TestViewSaving(common.TransactionCase):
|
|||
self.cr, self.uid, self.arch, context=None)
|
||||
|
||||
expect = [
|
||||
h.SPAN("My Company", attrs(model='res.company', id=1, field='name')),
|
||||
h.SPAN("+00 00 000 00 0 000", attrs(model='res.company', id=1, field='phone')),
|
||||
h.SPAN("My Company", attrs(model='res.company', id=1, field='name', type='char')),
|
||||
h.SPAN("+00 00 000 00 0 000", attrs(model='res.company', id=1, field='phone', type='char')),
|
||||
]
|
||||
for actual, expected in itertools.izip_longest(fields, expect):
|
||||
self.eq(actual, expected)
|
||||
|
||||
def test_embedded_save(self):
|
||||
embedded = h.SPAN("+00 00 000 00 0 000", attrs(model='res.company', id=1, field='phone'))
|
||||
embedded = h.SPAN("+00 00 000 00 0 000", attrs(
|
||||
model='res.company', id=1, field='phone', type='char'))
|
||||
|
||||
self.registry('ir.ui.view').save_embedded_field(self.cr, self.uid, embedded)
|
||||
|
||||
|
@ -118,8 +119,8 @@ class TestViewSaving(common.TransactionCase):
|
|||
h.H3("Column 2"),
|
||||
h.UL(
|
||||
h.LI("Item 1"),
|
||||
h.LI(h.SPAN("My Company", attrs(model='res.company', id=1, field='name'))),
|
||||
h.LI(h.SPAN("+00 00 000 00 0 000", attrs(model='res.company', id=1, field='phone')))
|
||||
h.LI(h.SPAN("My Company", attrs(model='res.company', id=1, field='name', type='char'))),
|
||||
h.LI(h.SPAN("+00 00 000 00 0 000", attrs(model='res.company', id=1, field='phone', type='char')))
|
||||
))
|
||||
))
|
||||
|
||||
|
@ -137,8 +138,8 @@ class TestViewSaving(common.TransactionCase):
|
|||
h.H3("Column 2"),
|
||||
h.UL(
|
||||
h.LI("wob wob wob"),
|
||||
h.LI(h.SPAN("Acme Corporation", attrs(model='res.company', id=1, field='name', expression="bob"))),
|
||||
h.LI(h.SPAN("+12 3456789", attrs(model='res.company', id=1, field='phone', expression="edmund"))),
|
||||
h.LI(h.SPAN("Acme Corporation", attrs(model='res.company', id=1, field='name', expression="bob", type='char'))),
|
||||
h.LI(h.SPAN("+12 3456789", attrs(model='res.company', id=1, field='phone', expression="edmund", type='char'))),
|
||||
)
|
||||
), encoding='utf-8')
|
||||
View.save(self.cr, self.uid, res_id=self.view_id, value=replacement,
|
||||
|
@ -173,7 +174,7 @@ class TestViewSaving(common.TransactionCase):
|
|||
|
||||
node = html.tostring(h.SPAN(
|
||||
"Acme Corporation",
|
||||
attrs(model='res.company', id=company_id, field="name", expression='bob')))
|
||||
attrs(model='res.company', id=company_id, field="name", expression='bob', type='char')))
|
||||
|
||||
self.registry('ir.ui.view').save(self.cr, self.uid, res_id=company_id,value=node)
|
||||
|
||||
|
@ -184,7 +185,9 @@ class TestViewSaving(common.TransactionCase):
|
|||
def test_field_tail(self):
|
||||
View = self.registry('ir.ui.view')
|
||||
replacement = ET.tostring(
|
||||
h.LI(h.SPAN("+12 3456789", attrs(model='res.company', id=1, field='phone', expression="edmund")),
|
||||
h.LI(h.SPAN("+12 3456789", attrs(
|
||||
model='res.company', id=1, type='char',
|
||||
field='phone', expression="edmund")),
|
||||
"whop whop"
|
||||
), encoding="utf-8")
|
||||
View.save(self.cr, self.uid, res_id = self.view_id, value=replacement,
|
||||
|
@ -203,7 +206,7 @@ class TestViewSaving(common.TransactionCase):
|
|||
h.H3("Column 2"),
|
||||
h.UL(
|
||||
h.LI("Item 1"),
|
||||
h.LI(h.SPAN("My Company", attrs(model='res.company', id=1, field='name'))),
|
||||
h.LI(h.SPAN("My Company", attrs(model='res.company', id=1, field='name', type='char'))),
|
||||
h.LI(h.SPAN({'t-field': "edmund"}), "whop whop"),
|
||||
))
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue