details: https://code.tryton.org/tryton/commit/815409359e6a
branch: default
user: Cédric Krier <[email protected]>
date: Thu Jun 25 16:50:42 2026 +0200
description:
Add search attribute to XML record tag
Closes #13247
diffstat:
trytond/CHANGELOG | 1 +
trytond/doc/topics/modules/index.rst | 3 ++
trytond/trytond/convert.py | 27 ++++++++++++++++++--
trytond/trytond/ir/ir.xml | 2 +-
trytond/trytond/ir/lang.xml | 48 ++++++++++++++++++------------------
trytond/trytond/tryton.rnc | 1 +
6 files changed, 54 insertions(+), 28 deletions(-)
diffs (328 lines):
diff -r 7ccbc1b89620 -r 815409359e6a trytond/CHANGELOG
--- a/trytond/CHANGELOG Mon Jul 13 15:56:31 2026 +0200
+++ b/trytond/CHANGELOG Thu Jun 25 16:50:42 2026 +0200
@@ -1,3 +1,4 @@
+* Add search attribute to XML record tag
* Enforce access right on the email template record (issue14907)
* Add ModelAccessProxy (issue14907)
* Restrict Genshi evaluation (issue14869, issue5160)
diff -r 7ccbc1b89620 -r 815409359e6a trytond/doc/topics/modules/index.rst
--- a/trytond/doc/topics/modules/index.rst Mon Jul 13 15:56:31 2026 +0200
+++ b/trytond/doc/topics/modules/index.rst Thu Jun 25 16:50:42 2026 +0200
@@ -184,6 +184,9 @@
database.
The ``id`` attribute can be used to refer to the record later in any XML
file.
+ The ``search`` attribute may be set as a domain which is used to search for
+ existing record instead of creating a new one when the ``id`` is not yet
+ known.
``field``
Set the value of the field with the name defined by the attribute ``name``.
diff -r 7ccbc1b89620 -r 815409359e6a trytond/trytond/convert.py
--- a/trytond/trytond/convert.py Mon Jul 13 15:56:31 2026 +0200
+++ b/trytond/trytond/convert.py Thu Jun 25 16:50:42 2026 +0200
@@ -190,6 +190,7 @@
self.xml_ids = []
self.model = None
self.xml_id = None
+ self.search_domain = None
self.update = None
self.values = None
self.current_field = None
@@ -206,6 +207,7 @@
except KeyError:
self.xml_id = None
raise ParsingError("missing 'id' attribute")
+ self.search_domain = attributes.get('search', None)
self.model = self.mh.pool.get(attributes["model"])
@@ -324,7 +326,8 @@
if self.xml_id in self.xml_ids and not self.update:
raise ParsingError("duplicate id: %s" % self.xml_id)
self.mh.import_record(
- self.model.__name__, self.values, self.xml_id)
+ self.model.__name__, self.values, self.xml_id,
+ self.search_domain)
self.xml_ids.append(self.xml_id)
return None
else:
@@ -534,7 +537,7 @@
], order=[('id', 'DESC')])
return set(rec.fs_id for rec in module_data)
- def import_record(self, model, values, fs_id):
+ def import_record(self, model, values, fs_id, domain=None):
module = self.module
if not fs_id:
@@ -549,7 +552,25 @@
# This means that the corresponding record have been found.
self.to_delete.discard(fs_id)
- if self.fs2db.exists(module, fs_id):
+ exists = self.fs2db.exists(module, fs_id)
+ if not exists and domain:
+ Model = self.pool.get(model)
+ records = Model.search(eval(domain), limit=1)
+ if records:
+ record, = records
+ mdata = self.ModelData(
+ fs_id=fs_id,
+ model=model,
+ module=module,
+ db_id=record.id,
+ field_names=(),
+ noupdate=self.noupdate,
+ )
+ self.fs2db.set(module, fs_id, mdata)
+ self.grouped_model_data.add(mdata)
+ exists = True
+
+ if exists:
if self.noupdate and self.module_state != 'to activate':
return
mdata = self.fs2db.get(module, fs_id)
diff -r 7ccbc1b89620 -r 815409359e6a trytond/trytond/ir/ir.xml
--- a/trytond/trytond/ir/ir.xml Mon Jul 13 15:56:31 2026 +0200
+++ b/trytond/trytond/ir/ir.xml Thu Jun 25 16:50:42 2026 +0200
@@ -6,7 +6,7 @@
<!--
lang_en is defined here to be in translation lang selection
-->
- <record model="ir.lang" id="lang_en">
+ <record model="ir.lang" id="lang_en" search="[('code', '=', 'en')]">
<field name="code">en</field>
<field name="name">English</field>
<field name="nplurals" eval="2"/>
diff -r 7ccbc1b89620 -r 815409359e6a trytond/trytond/ir/lang.xml
--- a/trytond/trytond/ir/lang.xml Mon Jul 13 15:56:31 2026 +0200
+++ b/trytond/trytond/ir/lang.xml Thu Jun 25 16:50:42 2026 +0200
@@ -10,7 +10,7 @@
id="menu_localization"/>
</data>
<data grouped="1" noupdate="1">
- <record model="ir.lang" id="lang_bg">
+ <record model="ir.lang" id="lang_bg" search="[('code', '=', 'bg')]">
<field name="code">bg</field>
<field name="name">Bulgarian</field>
<field name="nplurals" eval="2"/>
@@ -33,7 +33,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_ca">
+ <record model="ir.lang" id="lang_ca" search="[('code', '=', 'ca')]">
<field name="code">ca</field>
<field name="name">Català</field>
<field name="nplurals" eval="2"/>
@@ -56,7 +56,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_cs">
+ <record model="ir.lang" id="lang_cs" search="[('code', '=', 'cs')]">
<field name="code">cs</field>
<field name="name">Czech</field>
<field name="nplurals" eval="3"/>
@@ -79,7 +79,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_de">
+ <record model="ir.lang" id="lang_de" search="[('code', '=', 'de')]">
<field name="code">de</field>
<field name="name">German</field>
<field name="nplurals" eval="2"/>
@@ -105,7 +105,7 @@
<!--
lang_en is defined in ir.xml
-->
- <record model="ir.lang" id="lang_es">
+ <record model="ir.lang" id="lang_es" search="[('code', '=', 'es')]">
<field name="code">es</field>
<field name="name">Spanish</field>
<field name="nplurals" eval="2"/>
@@ -128,7 +128,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_es_419">
+ <record model="ir.lang" id="lang_es_419" search="[('code', '=',
'es_419')]">
<field name="code">es_419</field>
<field name="name">Spanish (Latin American)</field>
<field name="nplurals" eval="2"/>
@@ -151,7 +151,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_et">
+ <record model="ir.lang" id="lang_et" search="[('code', '=', 'et')]">
<field name="code">et</field>
<field name="name">Estonian</field>
<field name="nplurals" eval="2"/>
@@ -172,7 +172,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_fa">
+ <record model="ir.lang" id="lang_fa" search="[('code', '=', 'fa')]">
<field name="code">fa</field>
<field name="name">Persian</field>
<field name="nplurals" eval="2"/>
@@ -196,7 +196,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_fi">
+ <record model="ir.lang" id="lang_fi" search="[('code', '=', 'fi')]">
<field name="code">fi</field>
<field name="name">Finnish</field>
<field name="nplurals" eval="2"/>
@@ -217,7 +217,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_fr">
+ <record model="ir.lang" id="lang_fr" search="[('code', '=', 'fr')]">
<field name="code">fr</field>
<field name="name">French</field>
<field name="nplurals" eval="2"/>
@@ -240,7 +240,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_hu">
+ <record model="ir.lang" id="lang_hu" search="[('code', '=', 'hu')]">
<field name="code">hu</field>
<field name="name">Hungarian</field>
<field name="nplurals" eval="2"/>
@@ -263,7 +263,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_id">
+ <record model="ir.lang" id="lang_id" search="[('code', '=', 'id')]">
<field name="code">id</field>
<field name="name">Indonesian</field>
<field name="nplurals" eval="1"/>
@@ -286,7 +286,7 @@
<field name="p_sep_by_space" eval="False"/>
<field name="n_sep_by_space" eval="False"/>
</record>
- <record model="ir.lang" id="lang_it">
+ <record model="ir.lang" id="lang_it" search="[('code', '=', 'it')]">
<field name="code">it</field>
<field name="name">Italian</field>
<field name="nplurals" eval="2"/>
@@ -309,7 +309,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_lo">
+ <record model="ir.lang" id="lang_lo" search="[('code', '=', 'lo')]">
<field name="code">lo</field>
<field name="name">Lao</field>
<field name="nplurals" eval="1"/>
@@ -332,7 +332,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_lt">
+ <record model="ir.lang" id="lang_lt" search="[('code', '=', 'lt')]">
<field name="code">lt</field>
<field name="name">Lithuanian</field>
<field name="nplurals" eval="3"/>
@@ -355,7 +355,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_nl">
+ <record model="ir.lang" id="lang_nl" search="[('code', '=', 'nl')]">
<field name="code">nl</field>
<field name="name">Dutch</field>
<field name="nplurals" eval="2"/>
@@ -378,7 +378,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_pl">
+ <record model="ir.lang" id="lang_pl" search="[('code', '=', 'pl')]">
<field name="code">pl</field>
<field name="name">Polish</field>
<field name="nplurals" eval="3"/>
@@ -401,7 +401,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_pt">
+ <record model="ir.lang" id="lang_pt" search="[('code', '=', 'pt')]">
<field name="code">pt</field>
<field name="name">Portuguese</field>
<field name="nplurals" eval="2"/>
@@ -424,7 +424,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_ro">
+ <record model="ir.lang" id="lang_ro" search="[('code', '=', 'ro')]">
<field name="code">ro</field>
<field name="name">Romanian</field>
<field name="nplurals" eval="3"/>
@@ -447,7 +447,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_ru">
+ <record model="ir.lang" id="lang_ru" search="[('code', '=', 'ru')]">
<field name="code">ru</field>
<field name="name">Russian</field>
<field name="nplurals" eval="3"/>
@@ -470,7 +470,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_sl">
+ <record model="ir.lang" id="lang_sl" search="[('code', '=', 'sl')]">
<field name="code">sl</field>
<field name="name">Slovenian</field>
<field name="nplurals" eval="4"/>
@@ -493,7 +493,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_tr">
+ <record model="ir.lang" id="lang_tr" search="[('code', '=', 'tr')]">
<field name="code">tr</field>
<field name="name">Turkish</field>
<field name="nplurals" eval="2"/>
@@ -514,7 +514,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_uk">
+ <record model="ir.lang" id="lang_uk" search="[('code', '=', 'uk')]">
<field name="code">uk</field>
<field name="name">Ukrainian</field>
<field name="nplurals" eval="3"/>
@@ -535,7 +535,7 @@
<field name="p_sep_by_space" eval="True"/>
<field name="n_sep_by_space" eval="True"/>
</record>
- <record model="ir.lang" id="lang_zh_CN">
+ <record model="ir.lang" id="lang_zh_CN" search="[('code', '=',
'zh_CN')]">
<field name="code">zh_CN</field>
<field name="name">Chinese Simplified</field>
<field name="nplurals" eval="1"/>
diff -r 7ccbc1b89620 -r 815409359e6a trytond/trytond/tryton.rnc
--- a/trytond/trytond/tryton.rnc Mon Jul 13 15:56:31 2026 +0200
+++ b/trytond/trytond/tryton.rnc Thu Jun 25 16:50:42 2026 +0200
@@ -12,6 +12,7 @@
record = element record { attlist.record, field* }
attlist.record &= attribute model { text }
attlist.record &= attribute id { text }
+attlist.record &= attribute search { text }?
attlist.record &=
[ a:defaultValue = "0" ] attribute update { "0" | "1" }?
field = element field { attlist.field, text }