diff --git a/addons/account/models/account_account.py b/addons/account/models/account_account.py
index 4638b9da74d..7344eb90193 100644
--- a/addons/account/models/account_account.py
+++ b/addons/account/models/account_account.py
@@ -597,12 +597,9 @@ class AccountAccount(models.Model):
self.name = name
self.code = code
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for account in self:
- name = account.code + ' ' + account.name
- result.append((account.id, name))
- return result
+ account.display_name = f"{account.code} {account.name}"
@api.returns('self', lambda value: value.id)
def copy(self, default=None):
@@ -701,7 +698,8 @@ class AccountAccount(models.Model):
"""
if 'import_file' in self.env.context:
code, name = self._split_code_name(name)
- return self.create({'code': code, 'name': name}).name_get()[0]
+ record = self.create({'code': code, 'name': name})
+ return record.id, record.display_name
raise ValidationError(_("Please create new accounts from the Chart of Accounts menu."))
@api.model_create_multi
@@ -828,15 +826,14 @@ class AccountGroup(models.Model):
if not group.code_prefix_start or group.code_prefix_start > group.code_prefix_end:
group.code_prefix_start = group.code_prefix_end
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for group in self:
prefix = group.code_prefix_start and str(group.code_prefix_start)
if prefix and group.code_prefix_end != group.code_prefix_start:
prefix += '-' + str(group.code_prefix_end)
name = (prefix and (prefix + ' ') or '') + group.name
- result.append((group.id, name))
- return result
+ group.display_name = name
+
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
diff --git a/addons/account/models/account_account_tag.py b/addons/account/models/account_account_tag.py
index 394ab1f255f..d8c5ed6e648 100644
--- a/addons/account/models/account_account_tag.py
+++ b/addons/account/models/account_account_tag.py
@@ -14,18 +14,15 @@ class AccountAccountTag(models.Model):
tax_negate = fields.Boolean(string="Negate Tax Balance", help="Check this box to negate the absolute value of the balance of the lines associated with this tag in tax report computation.")
country_id = fields.Many2one(string="Country", comodel_name='res.country', help="Country for which this tag is available, when applied on taxes.")
- def name_get(self):
+ def _compute_display_name(self):
if not self.env.company.multi_vat_foreign_country_ids:
- return super().name_get()
+ return super()._compute_display_name()
- res = []
for tag in self:
name = tag.name
if tag.applicability == "taxes" and tag.country_id and tag.country_id != self.env.company.account_fiscal_country_id:
name = _("%s (%s)", tag.name, tag.country_id.code)
- res.append((tag.id, name,))
-
- return res
+ tag.display_name = name
@api.model
def _get_tax_tags(self, tag_name, country_id):
diff --git a/addons/account/models/account_incoterms.py b/addons/account/models/account_incoterms.py
index 905ae7377e7..78b7de7ff36 100644
--- a/addons/account/models/account_incoterms.py
+++ b/addons/account/models/account_incoterms.py
@@ -18,6 +18,6 @@ class AccountIncoterms(models.Model):
'Active', default=True,
help="By unchecking the active field, you may hide an INCOTERM you will not use.")
- def name_get(self):
- return [(incoterm.id, '%s%s' % (incoterm.code and '[%s] ' % incoterm.code or '', incoterm.name))
- for incoterm in self]
+ def _compute_display_name(self):
+ for incoterm in self:
+ incoterm.display_name = '%s%s' % (incoterm.code and '[%s] ' % incoterm.code or '', incoterm.name)
diff --git a/addons/account/models/account_journal.py b/addons/account/models/account_journal.py
index 8f5f68c8775..58e3816aaf9 100644
--- a/addons/account/models/account_journal.py
+++ b/addons/account/models/account_journal.py
@@ -696,14 +696,12 @@ class AccountJournal(models.Model):
'journal_id': self,
}).id
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for journal in self:
name = journal.name
if journal.currency_id and journal.currency_id != journal.company_id.currency_id:
- name = "%s (%s)" % (name, journal.currency_id.name)
- res += [(journal.id, name)]
- return res
+ name = f"{name} ({journal.currency_id.name})"
+ journal.display_name = name
def action_configure_bank_journal(self):
""" This function is called by the "configure" button of bank journals,
diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index b405c724aba..7d99ed30dc6 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -2387,11 +2387,9 @@ class AccountMove(models.Model):
self.line_ids.unlink()
return super().unlink()
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for move in self:
- result.append((move.id, move._get_move_display_name(show_ref=True)))
- return result
+ move.display_name = move._get_move_display_name(show_ref=True)
def onchange(self, values, field_name, field_onchange):
if field_name in ('line_ids', 'invoice_line_ids'):
diff --git a/addons/account/models/account_move_line.py b/addons/account/models/account_move_line.py
index 29db1d10ffc..1c4ae08fa4c 100644
--- a/addons/account/models/account_move_line.py
+++ b/addons/account/models/account_move_line.py
@@ -1525,14 +1525,15 @@ class AccountMoveLine(models.Model):
return res
- def name_get(self):
- return [(line.id, " ".join(
- element for element in (
- line.move_id.name,
- line.ref and f"({line.ref})",
- line.name or line.product_id.display_name,
- ) if element
- )) for line in self]
+ def _compute_display_name(self):
+ for line in self:
+ line.display_name = " ".join(
+ element for element in (
+ line.move_id.name,
+ line.ref and f"({line.ref})",
+ line.name or line.product_id.display_name,
+ ) if element
+ )
def copy_data(self, default=None):
data_list = super().copy_data(default=default)
diff --git a/addons/account/models/account_payment.py b/addons/account/models/account_payment.py
index dbb78fc8967..436cdf26724 100644
--- a/addons/account/models/account_payment.py
+++ b/addons/account/models/account_payment.py
@@ -740,8 +740,9 @@ class AccountPayment(models.Model):
return res
@api.depends('move_id.name')
- def name_get(self):
- return [(payment.id, payment.move_id.name != '/' and payment.move_id.name or _('Draft Payment')) for payment in self]
+ def _compute_display_name(self):
+ for payment in self:
+ payment.display_name = payment.move_id.name if payment.move_id.name != '/' else _('Draft Payment')
# -------------------------------------------------------------------------
# SYNCHRONIZATION account.payment <-> account.move
diff --git a/addons/account/models/account_payment_method.py b/addons/account/models/account_payment_method.py
index eb99b76bc61..7ada71ce051 100644
--- a/addons/account/models/account_payment_method.py
+++ b/addons/account/models/account_payment_method.py
@@ -119,10 +119,11 @@ class AccountPaymentMethodLine(models.Model):
company_id = fields.Many2one(related='journal_id.company_id')
available_payment_method_ids = fields.Many2many(related='journal_id.available_payment_method_ids')
- def name_get(self):
- if self.env.context.get('show_payment_journal_id'):
- return [(method.id, "%s (%s)" % (method.name, method.journal_id.name)) for method in self]
- return super().name_get()
+ def _compute_display_name(self):
+ if not self.env.context.get('show_payment_journal_id'):
+ return super()._compute_display_name()
+ for method in self:
+ method.display_name = f"{method.name} ({method.journal_id.name})"
@api.depends('payment_method_id.name')
def _compute_name(self):
diff --git a/addons/account/models/account_report.py b/addons/account/models/account_report.py
index 5e920647afb..ab1fcc3f1ad 100644
--- a/addons/account/models/account_report.py
+++ b/addons/account/models/account_report.py
@@ -203,11 +203,9 @@ class AccountReport(models.Model):
return name
@api.depends('name', 'country_id')
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for report in self:
- result.append((report.id, report.name + (f' ({report.country_id.code})' if report.country_id else '')))
- return result
+ report.display_name = report.name + (f' ({report.country_id.code})' if report.country_id else '')
class AccountReportLine(models.Model):
@@ -561,8 +559,10 @@ class AccountReportExpression(models.Model):
tags_to_archive.active = False
tags_to_unlink.unlink()
- def name_get(self):
- return [(expr.id, f'{expr.report_line_name} [{expr.label}]') for expr in self]
+ def _compute_display_name(self):
+ for expr in self:
+ expr.display_name = f'{expr.report_line_name} [{expr.label}]'
+
def _expand_aggregations(self):
"""Return self and its full aggregation expression dependency"""
diff --git a/addons/account/models/account_tax.py b/addons/account/models/account_tax.py
index 487ff06810a..7baf3ac44fa 100644
--- a/addons/account/models/account_tax.py
+++ b/addons/account/models/account_tax.py
@@ -362,8 +362,7 @@ class AccountTax(models.Model):
default['name'] = _("%s (Copy)") % self.name
return super(AccountTax, self).copy(default=default)
- def name_get(self):
- name_list = []
+ def _compute_display_name(self):
type_tax_use = dict(self._fields['type_tax_use']._description_selection(self.env))
tax_scope = dict(self._fields['tax_scope']._description_selection(self.env))
for record in self:
@@ -372,8 +371,7 @@ class AccountTax(models.Model):
name += ' (%s)' % type_tax_use.get(record.type_tax_use)
if record.tax_scope:
name += ' (%s)' % tax_scope.get(record.tax_scope)
- name_list += [(record.id, name)]
- return name_list
+ record.display_name = name
@api.onchange('amount')
def onchange_amount(self):
diff --git a/addons/account/models/res_partner_bank.py b/addons/account/models/res_partner_bank.py
index e20b9d1dccf..81f608d9490 100644
--- a/addons/account/models/res_partner_bank.py
+++ b/addons/account/models/res_partner_bank.py
@@ -307,15 +307,13 @@ class ResPartnerBank(models.Model):
account.partner_id._message_log(body=msg)
return super().unlink()
- def name_get(self):
- res = super().name_get()
+ def _compute_display_name(self):
+ super()._compute_display_name()
if self.env.context.get('display_account_trust'):
- res = []
for acc in self:
trusted_label = _('trusted') if acc.allow_out_payment else _('untrusted')
if acc.bank_id:
- name = '{} - {} ({})'.format(acc.acc_number, acc.bank_id.name, trusted_label)
+ name = f'{acc.acc_number} - {acc.bank_id.name} ({trusted_label})'
else:
- name = '{} ({})'.format(acc.acc_number, trusted_label)
- res.append((acc.id, name))
- return res
+ name = f'{acc.acc_number} ({trusted_label})'
+ acc.display_name = name
diff --git a/addons/analytic/models/analytic_account.py b/addons/analytic/models/analytic_account.py
index b18bb9a1f2a..566b5372fe2 100644
--- a/addons/analytic/models/analytic_account.py
+++ b/addons/analytic/models/analytic_account.py
@@ -115,16 +115,14 @@ class AccountAnalyticAccount(models.Model):
if self._cr.fetchone():
raise UserError(_("You can't set a different company on your analytic account since there are some analytic items linked to it."))
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for analytic in self:
name = analytic.name
if analytic.code:
name = f'[{analytic.code}] {name}'
if analytic.partner_id.commercial_partner_id.name:
name = f'{name} - {analytic.partner_id.commercial_partner_id.name}'
- res.append((analytic.id, name))
- return res
+ analytic.display_name = name
def copy_data(self, default=None):
default = dict(default or {})
diff --git a/addons/base_address_extended/models/res_city.py b/addons/base_address_extended/models/res_city.py
index b45c4584de4..18bcc6ccbfa 100644
--- a/addons/base_address_extended/models/res_city.py
+++ b/addons/base_address_extended/models/res_city.py
@@ -15,9 +15,7 @@ class City(models.Model):
country_id = fields.Many2one(comodel_name='res.country', string='Country', required=True)
state_id = fields.Many2one(comodel_name='res.country.state', string='State', domain="[('country_id', '=', country_id)]")
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for city in self:
- name = city.name if not city.zipcode else '%s (%s)' % (city.name, city.zipcode)
- res.append((city.id, name))
- return res
+ name = city.name if not city.zipcode else f'{city.name} ({city.zipcode})'
+ city.display_name = name
diff --git a/addons/base_sparse_field/models/fields.py b/addons/base_sparse_field/models/fields.py
index 4da062703d7..466982e734d 100644
--- a/addons/base_sparse_field/models/fields.py
+++ b/addons/base_sparse_field/models/fields.py
@@ -59,7 +59,7 @@ def _compute_sparse(self, records):
def _inverse_sparse(self, records):
for record in records:
values = record[self.sparse]
- value = self.convert_to_read(record[self.name], record, use_name_get=False)
+ value = self.convert_to_read(record[self.name], record, use_display_name=False)
if value:
if values.get(self.name) != value:
values[self.name] = value
diff --git a/addons/calendar/models/calendar_event.py b/addons/calendar/models/calendar_event.py
index c597f068264..b3c7be02f7e 100644
--- a/addons/calendar/models/calendar_event.py
+++ b/addons/calendar/models/calendar_event.py
@@ -645,7 +645,7 @@ class Meeting(models.Model):
return True
- def name_get(self):
+ def _compute_display_name(self):
""" Hide private events' name for events which don't belong to the current user
"""
hidden = self.filtered(
@@ -654,11 +654,8 @@ class Meeting(models.Model):
evt.user_id.id != self.env.uid and
self.env.user.partner_id not in evt.partner_ids
)
-
- shown = self - hidden
- shown_names = super(Meeting, shown).name_get()
- obfuscated_names = [(eid, _('Busy')) for eid in hidden.ids]
- return shown_names + obfuscated_names
+ hidden.display_name = _('Busy')
+ super(Meeting, self - hidden)._compute_display_name()
@api.model
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
diff --git a/addons/crm_iap_mine/models/crm_iap_lead_role.py b/addons/crm_iap_mine/models/crm_iap_lead_role.py
index 6ab177b30fc..98e869eb4e0 100644
--- a/addons/crm_iap_mine/models/crm_iap_lead_role.py
+++ b/addons/crm_iap_mine/models/crm_iap_lead_role.py
@@ -18,8 +18,9 @@ class PeopleRole(models.Model):
]
@api.depends('name')
- def name_get(self):
- return [(role.id, role.name.replace('_', ' ').title()) for role in self]
+ def _compute_display_name(self):
+ for role in self:
+ role.display_name = role.name.replace('_', ' ').title()
class PeopleSeniority(models.Model):
@@ -35,5 +36,6 @@ class PeopleSeniority(models.Model):
]
@api.depends('name')
- def name_get(self):
- return [(seniority.id, seniority.name.replace('_', ' ').title()) for seniority in self]
+ def _compute_display_name(self):
+ for seniority in self:
+ seniority.display_name = seniority.name.replace('_', ' ').title()
diff --git a/addons/crm_iap_mine/models/crm_iap_lead_seniority.py b/addons/crm_iap_mine/models/crm_iap_lead_seniority.py
index f110c4f69ca..50211413bf8 100644
--- a/addons/crm_iap_mine/models/crm_iap_lead_seniority.py
+++ b/addons/crm_iap_mine/models/crm_iap_lead_seniority.py
@@ -17,5 +17,6 @@ class PeopleSeniority(models.Model):
]
@api.depends('name')
- def name_get(self):
- return [(seniority.id, seniority.name.replace('_', ' ').title()) for seniority in self]
+ def _compute_display_name(self):
+ for seniority in self:
+ seniority.display_name = seniority.name.replace('_', ' ').title()
diff --git a/addons/event/models/event_event.py b/addons/event/models/event_event.py
index 4aacad1a68f..0793dc6ea7d 100644
--- a/addons/event/models/event_event.py
+++ b/addons/event/models/event_event.py
@@ -589,11 +589,10 @@ class EventEvent(models.Model):
self.message_subscribe([vals['organizer_id']])
return res
- def name_get(self):
+ def _compute_display_name(self):
"""Adds ticket seats availability if requested by context."""
if not self.env.context.get('name_with_seats_availability'):
- return super().name_get()
- res = []
+ return super()._compute_display_name()
for event in self:
# event or its tickets are sold out
if event.event_registrations_sold_out:
@@ -606,8 +605,7 @@ class EventEvent(models.Model):
)
else:
name = event.name
- res.append((event.id, name))
- return res
+ event.display_name = name
@api.returns('self', lambda value: value.id)
def copy(self, default=None):
diff --git a/addons/event/models/event_registration.py b/addons/event/models/event_registration.py
index 15456493a58..cc3cac72253 100644
--- a/addons/event/models/event_registration.py
+++ b/addons/event/models/event_registration.py
@@ -162,10 +162,11 @@ class EventRegistration(models.Model):
return ret
- def name_get(self):
- """ Custom name_get in case a registration is nott linked to an attendee
+ def _compute_display_name(self):
+ """ Custom display_name in case a registration is nott linked to an attendee
"""
- return [(registration.id, registration.name or f"#{registration.id}") for registration in self]
+ for registration in self:
+ registration.display_name = registration.name or f"#{registration.id}"
def toggle_active(self):
pre_inactive = self - self.filtered(self._active_name)
diff --git a/addons/event/models/event_ticket.py b/addons/event/models/event_ticket.py
index 711610301ce..f8f5263fc82 100644
--- a/addons/event/models/event_ticket.py
+++ b/addons/event/models/event_ticket.py
@@ -163,11 +163,10 @@ class EventTicket(models.Model):
raise ValidationError(_('There are not enough seats available for:')
+ '\n%s\n' % '\n'.join(sold_out_tickets))
- def name_get(self):
+ def _compute_display_name(self):
"""Adds ticket seats availability if requested by context."""
if not self.env.context.get('name_with_seats_availability'):
- return super().name_get()
- res = []
+ return super()._compute_display_name()
for ticket in self:
if not ticket.seats_max:
name = ticket.name
@@ -179,8 +178,7 @@ class EventTicket(models.Model):
ticket_name=ticket.name,
count=formatLang(self.env, ticket.seats_available, digits=0),
)
- res.append((ticket.id, name))
- return res
+ ticket.display_name = name
def _get_ticket_multiline_description(self):
""" Compute a multiline description of this ticket. It is used when ticket
diff --git a/addons/fleet/models/fleet_vehicle_assignation_log.py b/addons/fleet/models/fleet_vehicle_assignation_log.py
index 29092569802..ff55dde66c0 100644
--- a/addons/fleet/models/fleet_vehicle_assignation_log.py
+++ b/addons/fleet/models/fleet_vehicle_assignation_log.py
@@ -14,5 +14,6 @@ class FleetVehicleAssignationLog(models.Model):
date_start = fields.Date(string="Start Date")
date_end = fields.Date(string="End Date")
- def name_get(self):
- return [(rec.id, f'{rec.vehicle_id.name} - {rec.driver_id.name}') for rec in self]
+ def _compute_display_name(self):
+ for rec in self:
+ rec.display_name = f'{rec.vehicle_id.name} - {rec.driver_id.name}'
diff --git a/addons/fleet/models/fleet_vehicle_model.py b/addons/fleet/models/fleet_vehicle_model.py
index 2d409f720cb..50294964c1d 100644
--- a/addons/fleet/models/fleet_vehicle_model.py
+++ b/addons/fleet/models/fleet_vehicle_model.py
@@ -53,14 +53,12 @@ class FleetVehicleModel(models.Model):
domain = expression.AND([name_domain, domain])
return self._search(domain, limit=limit, order=order)
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for record in self:
name = record.name
if record.brand_id.name:
- name = record.brand_id.name + '/' + name
- res.append((record.id, name))
- return res
+ name = f"{record.brand_id.name}/{name}"
+ record.display_name = name
def _compute_vehicle_count(self):
group = self.env['fleet.vehicle']._read_group(
diff --git a/addons/gamification/models/gamification_challenge.py b/addons/gamification/models/gamification_challenge.py
index f0efb43283d..938cf513c6f 100644
--- a/addons/gamification/models/gamification_challenge.py
+++ b/addons/gamification/models/gamification_challenge.py
@@ -698,11 +698,10 @@ class Challenge(models.Model):
message_body = _("The challenge %s is finished.", challenge.name)
if rewarded_users:
- user_names = rewarded_users.name_get()
message_body += Markup("
") + _(
"Reward (badge %(badge_name)s) for every succeeding user was sent to %(users)s.",
badge_name=challenge.reward_id.name,
- users=", ".join(name for (user_id, name) in user_names)
+ users=", ".join(rewarded_users.mapped('display_name'))
)
else:
message_body += Markup("
") + _("Nobody has succeeded to reach every goal, no badge is rewarded for this challenge.")
diff --git a/addons/hr/models/hr_department.py b/addons/hr/models/hr_department.py
index 70abae88506..b8c61d73f26 100644
--- a/addons/hr/models/hr_department.py
+++ b/addons/hr/models/hr_department.py
@@ -31,14 +31,16 @@ class Department(models.Model):
master_department_id = fields.Many2one(
'hr.department', 'Master Department', compute='_compute_master_department_id', store=True)
- def name_get(self):
- if not self.env.context.get('hierarchical_naming', True):
- return [(record.id, record.name) for record in self]
- return super(Department, self).name_get()
+ def _compute_display_name(self):
+ if self.env.context.get('hierarchical_naming', True):
+ return super()._compute_display_name()
+ for record in self:
+ record.display_name = record.name
@api.model
def name_create(self, name):
- return self.create({'name': name}).name_get()[0]
+ record = self.create({'name': name})
+ return record.id, record.display_name
@api.depends('name', 'parent_id.complete_name')
def _compute_complete_name(self):
diff --git a/addons/hr/models/hr_employee.py b/addons/hr/models/hr_employee.py
index 93eb7b58e63..f4955f84e04 100644
--- a/addons/hr/models/hr_employee.py
+++ b/addons/hr/models/hr_employee.py
@@ -191,10 +191,11 @@ class HrEmployeePrivate(models.Model):
})
}
- def name_get(self):
+ def _compute_display_name(self):
if self.check_access_rights('read', raise_exception=False):
- return super(HrEmployeePrivate, self).name_get()
- return self.env['hr.employee.public'].browse(self.ids).name_get()
+ return super()._compute_display_name()
+ for employee_private, employee_public in zip(self, self.env['hr.employee.public'].browse(self.ids)):
+ employee_private.display_name = employee_public.display_name
def search_fetch(self, domain, field_names, offset=0, limit=None, order=None):
if self.check_access_rights('read', raise_exception=False):
diff --git a/addons/hr/models/res_partner.py b/addons/hr/models/res_partner.py
index 6b3ef53787d..5c8722744ff 100644
--- a/addons/hr/models/res_partner.py
+++ b/addons/hr/models/res_partner.py
@@ -13,17 +13,17 @@ class Partner(models.Model):
help="Related employees based on their private address")
employees_count = fields.Integer(compute='_compute_employees_count', groups="hr.group_hr_user")
- def name_get(self):
+ def _compute_display_name(self):
""" Override to allow an employee to see its private address in his profile.
This avoids to relax access rules on `res.parter` and to add an `ir.rule`.
(advantage in both security and performance).
Use a try/except instead of systematically checking to minimize the impact on performance.
"""
try:
- return super(Partner, self).name_get()
+ super()._compute_display_name()
except AccessError as e:
if len(self) == 1 and self in self.env.user.employee_ids.mapped('address_home_id'):
- return super(Partner, self.sudo()).name_get()
+ super(Partner, self.sudo())._compute_display_name()
raise e
def _compute_employees_count(self):
diff --git a/addons/hr_attendance/models/hr_attendance.py b/addons/hr_attendance/models/hr_attendance.py
index c0dcfd3df98..80a6640cded 100644
--- a/addons/hr_attendance/models/hr_attendance.py
+++ b/addons/hr_attendance/models/hr_attendance.py
@@ -31,21 +31,21 @@ class HrAttendance(models.Model):
check_out = fields.Datetime(string="Check Out")
worked_hours = fields.Float(string='Worked Hours', compute='_compute_worked_hours', store=True, readonly=True)
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for attendance in self:
if not attendance.check_out:
- result.append((attendance.id, _("%(empl_name)s from %(check_in)s") % {
- 'empl_name': attendance.employee_id.name,
- 'check_in': format_datetime(self.env, attendance.check_in, dt_format=False),
- }))
+ attendance.display_name = _(
+ "%s from %s",
+ attendance.employee_id.name,
+ format_datetime(self.env, attendance.check_in, dt_format=False)
+ )
else:
- result.append((attendance.id, _("%(empl_name)s from %(check_in)s to %(check_out)s") % {
- 'empl_name': attendance.employee_id.name,
- 'check_in': format_datetime(self.env, attendance.check_in, dt_format=False),
- 'check_out': format_datetime(self.env, attendance.check_out, dt_format=False),
- }))
- return result
+ attendance.display_name = _(
+ "%s from %s to %s",
+ attendance.employee_id.name,
+ format_datetime(self.env, attendance.check_in, dt_format=False),
+ format_datetime(self.env, attendance.check_out, dt_format=False),
+ )
def _get_employee_calendar(self):
self.ensure_one()
diff --git a/addons/hr_contract/report/hr_contract_history.py b/addons/hr_contract/report/hr_contract_history.py
index 26ea29198bf..af3bca153a6 100644
--- a/addons/hr_contract/report/hr_contract_history.py
+++ b/addons/hr_contract/report/hr_contract_history.py
@@ -17,7 +17,6 @@ class ContractHistory(models.Model):
# to the employee. That's why we will use this id (employee_id) as the id of the hr.contract.history.
contract_id = fields.Many2one('hr.contract', readonly=True)
- display_name = fields.Char(compute='_compute_display_name')
name = fields.Char('Contract Name', readonly=True)
date_hired = fields.Date('Hire Date', readonly=True)
date_start = fields.Date('Start Date', readonly=True)
diff --git a/addons/hr_holidays/models/hr_department.py b/addons/hr_holidays/models/hr_department.py
index 725641f7802..8893eb4520b 100644
--- a/addons/hr_holidays/models/hr_department.py
+++ b/addons/hr_holidays/models/hr_department.py
@@ -61,7 +61,7 @@ class Department(models.Model):
**self._get_action_context(),
'search_default_active_time_off': 3,
'hide_employee_name': 1,
- 'holiday_status_name_get': False
+ 'holiday_status_display_name': False
}
return action
diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py
index 9c8a8177930..0c5db995f06 100644
--- a/addons/hr_holidays/models/hr_leave.py
+++ b/addons/hr_holidays/models/hr_leave.py
@@ -82,7 +82,7 @@ class HolidaysRequest(models.Model):
defaults = super(HolidaysRequest, self).default_get(fields_list)
defaults = self._default_get_request_parameters(defaults)
- if self.env.context.get('holiday_status_name_get', True) and 'holiday_status_id' in fields_list and not defaults.get('holiday_status_id'):
+ if self.env.context.get('holiday_status_display_name', True) and 'holiday_status_id' in fields_list and not defaults.get('holiday_status_id'):
lt = self.env['hr.leave.type'].search(['|', ('requires_allocation', '=', 'no'), ('has_valid_allocation', '=', True)], limit=1, order='sequence')
if lt:
@@ -774,19 +774,6 @@ class HolidaysRequest(models.Model):
@api.depends('employee_id', 'holiday_status_id')
def _compute_display_name(self):
- super()._compute_display_name()
-
- def onchange(self, values, field_name, field_onchange):
- # Try to force the leave_type name_get when creating new records
- # This is called right after pressing create and returns the name_get for
- # most fields in the view.
- if field_onchange.get('employee_id') and 'employee_id' not in self._context and values:
- employee_id = get_employee_from_context(values, self._context, self.env.user.employee_id.id)
- self = self.with_context(employee_id=employee_id)
- return super().onchange(values, field_name, field_onchange)
-
- def name_get(self):
- res = []
for leave in self:
user_tz = timezone(leave.tz)
date_from_utc = leave.date_from and leave.date_from.astimezone(user_tz).date()
@@ -795,13 +782,9 @@ class HolidaysRequest(models.Model):
if self.env.context.get('short_name'):
short_leave_name = leave.name or time_off_type_display or _('Time Off')
if leave.leave_type_request_unit == 'hour':
- res.append((
- leave.id,
- _("%s: %.2f hours") % (short_leave_name, leave.number_of_hours_display)))
+ leave.display_name = _("%s: %.2f hours", short_leave_name, leave.number_of_hours_display)
else:
- res.append((
- leave.id,
- _("%s: %.2f days") % (short_leave_name, leave.number_of_days)))
+ leave.display_name = _("%s: %.2f days", short_leave_name, leave.number_of_days)
else:
if leave.holiday_type == 'company':
target = leave.mode_company_id.name
@@ -816,65 +799,55 @@ class HolidaysRequest(models.Model):
display_date = format_date(self.env, date_from_utc) or ""
if leave.leave_type_request_unit == 'hour':
if self.env.context.get('hide_employee_name') and 'employee_id' in self.env.context.get('group_by', []):
- res.append((
- leave.id,
- _("%(leave_type)s: %(duration).2f hours on %(date)s",
- leave_type=time_off_type_display,
- duration=leave.number_of_hours_display,
- date=fields.Date.to_string(date_from_utc) or "",
- )
- ))
+ leave.display_name = _("%(leave_type)s: %(duration).2f hours on %(date)s",
+ leave_type=time_off_type_display,
+ duration=leave.number_of_hours_display,
+ date=fields.Date.to_string(date_from_utc) or "",
+ )
elif not time_off_type_display:
- res.append((
- leave.id,
- _("%(person)s: %(duration).2f hours on %(date)s",
- person=target,
- duration=leave.number_of_hours_display,
- date=display_date,
- )
- ))
+ leave.display_name = _("%(person)s: %(duration).2f hours on %(date)s",
+ person=target,
+ duration=leave.number_of_hours_display,
+ date=display_date,
+ )
else:
- res.append((
- leave.id,
- _("%(person)s on %(leave_type)s: %(duration).2f hours on %(date)s",
- person=target,
- leave_type=time_off_type_display,
- duration=leave.number_of_hours_display,
- date=display_date,
- )
- ))
+ leave.display_name = _("%(person)s on %(leave_type)s: %(duration).2f hours on %(date)s",
+ person=target,
+ leave_type=time_off_type_display,
+ duration=leave.number_of_hours_display,
+ date=display_date,
+ )
else:
if leave.number_of_days > 1 and date_from_utc and date_to_utc:
display_date += ' / %s' % format_date(self.env, date_to_utc) or ""
if not target or self.env.context.get('hide_employee_name') and 'employee_id' in self.env.context.get('group_by', []):
- res.append((
- leave.id,
- _("%(leave_type)s: %(duration).2f days (%(start)s)",
- leave_type=time_off_type_display,
- duration=leave.number_of_days,
- start=display_date,
- )
- ))
+ leave.display_name = _("%(leave_type)s: %(duration).2f days (%(start)s)",
+ leave_type=time_off_type_display,
+ duration=leave.number_of_days,
+ start=display_date,
+ )
elif not time_off_type_display:
- res.append((
- leave.id,
- _("%(person)s: %(duration).2f days (%(start)s)",
- person=target,
- duration=leave.number_of_days,
- start=display_date,
- )
- ))
+ leave.display_name = _("%(person)s: %(duration).2f days (%(start)s)",
+ person=target,
+ duration=leave.number_of_days,
+ start=display_date,
+ )
else:
- res.append((
- leave.id,
- _("%(person)s on %(leave_type)s: %(duration).2f days (%(start)s)",
- person=target,
- leave_type=time_off_type_display,
- duration=leave.number_of_days,
- start=display_date,
- )
- ))
- return res
+ leave.display_name = _("%(person)s on %(leave_type)s: %(duration).2f days (%(start)s)",
+ person=target,
+ leave_type=time_off_type_display,
+ duration=leave.number_of_days,
+ start=display_date,
+ )
+
+ def onchange(self, values, field_name, field_onchange):
+ # Try to force the leave_type display_name when creating new records
+ # This is called right after pressing create and returns the display_name for
+ # most fields in the view.
+ if field_onchange.get('employee_id') and 'employee_id' not in self._context and values:
+ employee_id = get_employee_from_context(values, self._context, self.env.user.employee_id.id)
+ self = self.with_context(employee_id=employee_id)
+ return super().onchange(values, field_name, field_onchange)
def add_follower(self, employee_id):
employee = self.env['hr.employee'].browse(employee_id)
@@ -1373,18 +1346,16 @@ class HolidaysRequest(models.Model):
def _notify_manager(self):
leaves = self.filtered(lambda hol: (hol.validation_type == 'both' and hol.state in ['validate1', 'validate']) or (hol.validation_type == 'manager' and hol.state == 'validate'))
- holiday_names = self.name_get()
for holiday in leaves:
responsible = holiday.employee_id.leave_manager_id.partner_id.ids
if responsible:
- holiday_name = list(filter(lambda h: holiday.id in h, holiday_names))[0][1]
self.env['mail.thread'].sudo().message_notify(
partner_ids=responsible,
model_description='Time Off',
subject=_('Refused Time Off'),
body=_(
'%(holiday_name)s has been refused.',
- holiday_name=holiday_name,
+ holiday_name=holiday.display_name,
),
email_layout_xmlid='mail.mail_notification_light',
)
@@ -1397,7 +1368,6 @@ class HolidaysRequest(models.Model):
self._force_cancel(reason, 'mail.mt_note')
def _force_cancel(self, reason, msg_subtype='mail.mt_comment'):
- leave_names = self.name_get()
recs = self.browse() if self.env.context.get(MODULE_UNINSTALL_FLAG) else self
for leave in recs:
leave.message_post(
@@ -1418,14 +1388,13 @@ class HolidaysRequest(models.Model):
responsibles |= leave.holiday_status_id.responsible_ids.partner_id
if responsibles:
- leave_name = list(filter(lambda h: leave.id in h, leave_names))[0][1]
self.env['mail.thread'].sudo().message_notify(
partner_ids=responsibles.ids,
model_description='Time Off',
subject=_('Canceled Time Off'),
body=_(
"%(leave_name)s has been cancelled with the justification:
%(reason)s.",
- leave_name=leave_name,
+ leave_name=leave.display_name,
reason=reason
),
email_layout_xmlid='mail.mail_notification_light',
diff --git a/addons/hr_holidays/models/hr_leave_allocation.py b/addons/hr_holidays/models/hr_leave_allocation.py
index 693582195c4..75d7aa6f4cc 100644
--- a/addons/hr_holidays/models/hr_leave_allocation.py
+++ b/addons/hr_holidays/models/hr_leave_allocation.py
@@ -520,16 +520,15 @@ class HolidaysAllocation(models.Model):
####################################################
def onchange(self, values, field_name, field_onchange):
- # Try to force the leave_type name_get when creating new records
- # This is called right after pressing create and returns the name_get for
+ # Try to force the leave_type display_name when creating new records
+ # This is called right after pressing create and returns the display_name for
# most fields in the view.
if field_onchange.get('employee_id') and 'employee_id' not in self._context and values:
employee_id = get_employee_from_context(values, self._context, self.env.user.employee_id.id)
self = self.with_context(employee_id=employee_id)
return super().onchange(values, field_name, field_onchange)
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for allocation in self:
if allocation.holiday_type == 'company':
target = allocation.mode_company_id.name
@@ -542,16 +541,12 @@ class HolidaysAllocation(models.Model):
else:
target = ', '.join(allocation.employee_ids.sudo().mapped('name'))
- res.append(
- (allocation.id,
- _("Allocation of %(allocation_name)s: %(duration).2f %(duration_type)s to %(person)s",
- allocation_name=allocation.holiday_status_id.sudo().name,
- duration=allocation.number_of_hours_display if allocation.type_request_unit == 'hour' else allocation.number_of_days,
- duration_type=_('hours') if allocation.type_request_unit == 'hour' else _('days'),
- person=target
- ))
+ allocation.display_name = _("Allocation of %s: %.2f %s to %s",
+ allocation.holiday_status_id.sudo().name,
+ allocation.number_of_hours_display if allocation.type_request_unit == 'hour' else allocation.number_of_days,
+ _('hours') if allocation.type_request_unit == 'hour' else _('days'),
+ target,
)
- return res
def add_follower(self, employee_id):
employee = self.env['hr.employee'].browse(employee_id)
diff --git a/addons/hr_holidays/models/hr_leave_type.py b/addons/hr_holidays/models/hr_leave_type.py
index 7148eb5a3f2..fda87bdc930 100644
--- a/addons/hr_holidays/models/hr_leave_type.py
+++ b/addons/hr_holidays/models/hr_leave_type.py
@@ -537,26 +537,26 @@ class HolidaysType(models.Model):
if leave_type.employee_requests == 'no':
leave_type.allocation_validation_type = 'officer'
- def requested_name_get(self):
- return self._context.get('holiday_status_name_get', True) and self._context.get('employee_id')
+ def requested_display_name(self):
+ return self._context.get('holiday_status_display_name', True) and self._context.get('employee_id')
- def name_get(self):
- if not self.requested_name_get():
+ @api.depends('requires_allocation', 'virtual_remaining_leaves', 'max_leaves', 'request_unit')
+ @api.depends_context('holiday_status_display_name', 'employee_id', 'from_manager_leave_form')
+ def _compute_display_name(self):
+ if not self.requested_display_name():
# leave counts is based on employee_id, would be inaccurate if not based on correct employee
- return super(HolidaysType, self).name_get()
- res = []
+ return super()._compute_display_name()
for record in self:
name = record.name
if record.requires_allocation == "yes" and not self._context.get('from_manager_leave_form'):
- name = "%(name)s (%(count)s)" % {
- 'name': name,
- 'count': _('%g remaining out of %g') % (
+ name = "{name} ({count})".format(
+ name=name,
+ count=_('%g remaining out of %g') % (
float_round(record.virtual_remaining_leaves, precision_digits=2) or 0.0,
float_round(record.max_leaves, precision_digits=2) or 0.0,
- ) + (_(' hours') if record.request_unit == 'hour' else _(' days'))
- }
- res.append((record.id, name))
- return res
+ ) + (_(' hours') if record.request_unit == 'hour' else _(' days')),
+ )
+ record.display_name = name
@api.model
def _search(self, domain, offset=0, limit=None, order=None, access_rights_uid=None):
diff --git a/addons/hr_holidays/views/hr_leave_views.xml b/addons/hr_holidays/views/hr_leave_views.xml
index a8a7799bca3..5686201fb59 100644
--- a/addons/hr_holidays/views/hr_leave_views.xml
+++ b/addons/hr_holidays/views/hr_leave_views.xml
@@ -679,7 +679,7 @@
'search_default_active_employee': 3,
'search_default_active_time_off': 4,
'hide_employee_name': 1,
- 'holiday_status_name_get': False}
+ 'holiday_status_display_name': False}
['|', ('employee_id.company_id', 'in', allowed_company_ids),
'&', ('multi_employee', '=', True),
@@ -701,7 +701,7 @@
{
'hide_employee_name': 1,
- 'holiday_status_name_get': False}
+ 'holiday_status_display_name': False}
[('holiday_allocation_id', '=', active_id)]
diff --git a/addons/hr_holidays_attendance/models/hr_leave_type.py b/addons/hr_holidays_attendance/models/hr_leave_type.py
index 1995dc4d2d3..3119d0682e0 100644
--- a/addons/hr_holidays_attendance/models/hr_leave_type.py
+++ b/addons/hr_holidays_attendance/models/hr_leave_type.py
@@ -13,27 +13,24 @@ class HRLeaveType(models.Model):
"Deduct Extra Hours", default=False,
help="Once a time off of this type is approved, extra hours in attendances will be deducted.")
- def name_get(self):
+ @api.depends_context('request_type', 'leave', 'holiday_status_display_name', 'employee_id')
+ def _compute_display_name(self):
# Exclude hours available in allocation contexts, it might be confusing otherwise
- if not self.requested_name_get() or self._context.get('request_type', 'leave') == 'allocation':
- return super().name_get()
- employee_id = False
- overtime_leaves = self.env['hr.leave.type']
- res = []
- for leave_type in self:
- if leave_type.overtime_deductible and leave_type.requires_allocation == 'no':
- if not employee_id:
- employee_id = self.env['hr.employee'].browse(self._context.get('employee_id')).sudo()
- if employee_id.total_overtime > 0:
- overtime_leaves |= leave_type
- name = "%(name)s (%(count)s)" % {
- 'name': leave_type.name,
- 'count': _('%s hours available',
- format_duration(employee_id.total_overtime)),
- }
- res.append((leave_type.id, name))
- res += super(HRLeaveType, self - overtime_leaves).name_get()
- return res
+ if not self.requested_display_name() or self._context.get('request_type', 'leave') == 'allocation':
+ return super()._compute_display_name()
+
+ employee = self.env['hr.employee'].browse(self._context.get('employee_id')).sudo()
+ if employee.total_overtime <= 0:
+ return super()._compute_display_name()
+
+ overtime_leaves = self.filtered(lambda l_type: l_type.overtime_deductible and l_type.requires_allocation == 'no')
+ for leave_type in overtime_leaves:
+ leave_type.display_name = "%(name)s (%(count)s)" % {
+ 'name': leave_type.name,
+ 'count': _('%s hours available',
+ format_duration(employee.total_overtime)),
+ }
+ super(HRLeaveType, self - overtime_leaves)._compute_display_name()
def get_employees_days(self, employee_ids, date=None):
res = super().get_employees_days(employee_ids, date)
diff --git a/addons/hr_recruitment/models/hr_applicant.py b/addons/hr_recruitment/models/hr_applicant.py
index 4ea632695be..c0251ec7258 100644
--- a/addons/hr_recruitment/models/hr_applicant.py
+++ b/addons/hr_recruitment/models/hr_applicant.py
@@ -505,13 +505,11 @@ class Applicant(models.Model):
applicant._message_add_suggested_recipient(recipients, email=email_from, reason=_('Contact Email'))
return recipients
- def name_get(self):
- if self.env.context.get('show_partner_name'):
- return [
- (applicant.id, applicant.partner_name or applicant.name)
- for applicant in self
- ]
- return super().name_get()
+ def _compute_display_name(self):
+ if not self.env.context.get('show_partner_name'):
+ return super()._compute_display_name()
+ for applicant in self:
+ applicant.display_name = applicant.partner_name or applicant.name
@api.model
def message_new(self, msg, custom_values=None):
diff --git a/addons/hr_skills/models/hr_skill.py b/addons/hr_skills/models/hr_skill.py
index 1244cc69065..2a37e66b47d 100644
--- a/addons/hr_skills/models/hr_skill.py
+++ b/addons/hr_skills/models/hr_skill.py
@@ -13,7 +13,8 @@ class Skill(models.Model):
sequence = fields.Integer(default=10)
skill_type_id = fields.Many2one('hr.skill.type', required=True, ondelete='cascade')
- def name_get(self):
+ def _compute_display_name(self):
if not self._context.get('from_skill_dropdown'):
- return super().name_get()
- return [(record.id, f"{record.name} ({record.skill_type_id.name})") for record in self]
+ return super()._compute_display_name()
+ for record in self:
+ record.display_name = f"{record.name} ({record.skill_type_id.name})"
diff --git a/addons/hr_skills/models/hr_skill_level.py b/addons/hr_skills/models/hr_skill_level.py
index c879c501a3f..4edd74c6d47 100644
--- a/addons/hr_skills/models/hr_skill_level.py
+++ b/addons/hr_skills/models/hr_skill_level.py
@@ -19,10 +19,11 @@ class SkillLevel(models.Model):
('check_level_progress', 'CHECK(level_progress BETWEEN 0 AND 100)', "Progress should be a number between 0 and 100."),
]
- def name_get(self):
+ def _compute_display_name(self):
if not self._context.get('from_skill_level_dropdown'):
- return super().name_get()
- return [(record.id, f"{record.name} ({record.level_progress}%)") for record in self]
+ return super()._compute_display_name()
+ for record in self:
+ record.display_name = f"{record.name} ({record.level_progress}%)"
@api.model_create_multi
def create(self, vals_list):
diff --git a/addons/hr_timesheet/models/hr_employee.py b/addons/hr_timesheet/models/hr_employee.py
index 5cb1b687af4..38e721eb99d 100644
--- a/addons/hr_timesheet/models/hr_employee.py
+++ b/addons/hr_timesheet/models/hr_employee.py
@@ -23,13 +23,12 @@ class HrEmployee(models.Model):
for employee in self:
employee.has_timesheet = result.get(employee.id, False)
- def name_get(self):
- res = super().name_get()
+ def _compute_display_name(self):
+ super()._compute_display_name()
allowed_company_ids = self.env.context.get('allowed_company_ids', [])
if len(allowed_company_ids) <= 1:
- return res
+ return
- name_mapping = dict(res)
employees_count_per_user = {
user.id: count
for user, count in self.env['hr.employee'].sudo()._read_group(
@@ -40,8 +39,7 @@ class HrEmployee(models.Model):
}
for employee in self:
if employees_count_per_user.get(employee.user_id.id, 0) > 1:
- name_mapping[employee.id] = f'{name_mapping[employee.id]} - {employee.company_id.name}'
- return list(name_mapping.items())
+ employee.display_name = f'{employee.display_name} - {employee.company_id.name}'
def action_unlink_wizard(self):
wizard = self.env['hr.employee.delete.wizard'].create({
diff --git a/addons/hr_timesheet/models/hr_timesheet.py b/addons/hr_timesheet/models/hr_timesheet.py
index e3d7df5cdf6..1aaa8baabbc 100644
--- a/addons/hr_timesheet/models/hr_timesheet.py
+++ b/addons/hr_timesheet/models/hr_timesheet.py
@@ -65,23 +65,14 @@ class AccountAnalyticLine(models.Model):
partner_id = fields.Many2one(compute='_compute_partner_id', store=True, readonly=False)
readonly_timesheet = fields.Boolean(string="Readonly Timesheet", compute="_compute_readonly_timesheet")
- def name_get(self):
- result = super().name_get()
- timesheets_read = self.env[self._name].search_read([('project_id', '!=', False), ('id', 'in', self.ids)], ['id', 'project_id', 'task_id'])
- if not timesheets_read:
- return result
- def _get_display_name(project_id, task_id):
- """ Get the display name of the timesheet based on the project and task
- :param project_id: tuple containing the id and the display name of the project
- :param task_id: tuple containing the id and the display name of the task if a task exists in the timesheet
- otherwise False.
- :returns: the display name of the timesheet
- """
- if task_id:
- return '%s - %s' % (project_id[1], task_id[1])
- return project_id[1]
- timesheet_dict = {res['id']: _get_display_name(res['project_id'], res['task_id']) for res in timesheets_read}
- return list({**dict(result), **timesheet_dict}.items())
+ def _compute_display_name(self):
+ analytic_line_with_project = self.filtered('project_id')
+ super(AccountAnalyticLine, self - analytic_line_with_project)._compute_display_name()
+ for analytic_line in analytic_line_with_project:
+ if analytic_line.task_id:
+ analytic_line.display_name = f"{analytic_line.project_id.display_name} - {analytic_line.task_id.display_name}"
+ else:
+ analytic_line.display_name = analytic_line.project_id.display_name
def _is_readonly(self):
self.ensure_one()
diff --git a/addons/hr_timesheet/models/project_project.py b/addons/hr_timesheet/models/project_project.py
index 6cd07e1c059..f6a7d3d9692 100644
--- a/addons/hr_timesheet/models/project_project.py
+++ b/addons/hr_timesheet/models/project_project.py
@@ -164,15 +164,14 @@ class Project(models.Model):
project._create_analytic_account()
return super(Project, self).write(values)
- def name_get(self):
- res = super().name_get()
+ def _compute_display_name(self):
+ super()._compute_display_name()
if len(self.env.context.get('allowed_company_ids', [])) <= 1:
- return res
- name_mapping = dict(res)
+ return
+
for project in self:
if project.is_internal_project:
- name_mapping[project.id] = f'{name_mapping[project.id]} - {project.company_id.name}'
- return list(name_mapping.items())
+ project.display_name = f'{project.display_name} - {project.company_id.name}'
@api.model
def _init_data_analytic_account(self):
diff --git a/addons/hr_timesheet/models/project_task.py b/addons/hr_timesheet/models/project_task.py
index 3cbb10f1a40..6c66e8db0e9 100644
--- a/addons/hr_timesheet/models/project_task.py
+++ b/addons/hr_timesheet/models/project_task.py
@@ -181,13 +181,13 @@ class Task(models.Model):
return res
- def name_get(self):
+ def _compute_display_name(self):
+ super()._compute_display_name()
if self.env.context.get('hr_timesheet_display_remaining_hours'):
- name_mapping = dict(super().name_get())
for task in self:
if task.allow_timesheets and task.planned_hours > 0 and task.encode_uom_in_days:
days_left = _("(%s days remaining)") % task._convert_hours_to_days(task.remaining_hours)
- name_mapping[task.id] = name_mapping.get(task.id, '') + u"\u00A0" + days_left
+ task.display_name = task.display_name + "\u00A0" + days_left
elif task.allow_timesheets and task.planned_hours > 0:
hours, mins = (str(int(duration)).rjust(2, '0') for duration in divmod(abs(task.remaining_hours) * 60, 60))
hours_left = _(
@@ -196,9 +196,7 @@ class Task(models.Model):
hours=hours,
minutes=mins,
)
- name_mapping[task.id] = name_mapping.get(task.id, '') + u"\u00A0" + hours_left
- return list(name_mapping.items())
- return super().name_get()
+ task.display_name = task.display_name + "\u00A0" + hours_left
@api.model
def _get_view_cache_key(self, view_id=None, view_type='form', **options):
diff --git a/addons/http_routing/models/ir_http.py b/addons/http_routing/models/ir_http.py
index 3be942d5d18..4b8f9a8c62a 100644
--- a/addons/http_routing/models/ir_http.py
+++ b/addons/http_routing/models/ir_http.py
@@ -88,7 +88,6 @@ def slug(value):
try:
if not value.id:
raise ValueError("Cannot slug non-existent record %s" % value)
- # [(id, name)] = value.name_get()
identifier, name = value.id, getattr(value, 'seo_name', False) or value.display_name
except AttributeError:
# assume name_search result tuple
diff --git a/addons/im_livechat/models/chatbot_script_answer.py b/addons/im_livechat/models/chatbot_script_answer.py
index 7f12d4f04a2..34a9f70ec86 100644
--- a/addons/im_livechat/models/chatbot_script_answer.py
+++ b/addons/im_livechat/models/chatbot_script_answer.py
@@ -21,21 +21,15 @@ class ChatbotScriptAnswer(models.Model):
'chatbot.script.step', string='Script Step', required=True, ondelete='cascade')
chatbot_script_id = fields.Many2one(related='script_step_id.chatbot_script_id')
- def name_get(self):
+ def _compute_display_name(self):
if self._context.get('chatbot_script_answer_display_short_name'):
- return super().name_get()
+ return super()._compute_display_name()
- result = []
for answer in self:
answer_message = answer.script_step_id.message.replace('\n', ' ')
shortened_message = textwrap.shorten(answer_message, width=26, placeholder=" [...]")
- result.append((
- answer.id,
- "%s: %s" % (shortened_message, answer.name)
- ))
-
- return result
+ answer.display_name = f"{shortened_message}: {answer.name}"
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
diff --git a/addons/l10n_in_edi_ewaybill/models/ewaybill_type.py b/addons/l10n_in_edi_ewaybill/models/ewaybill_type.py
index bf9e6920c2a..a656d33a148 100755
--- a/addons/l10n_in_edi_ewaybill/models/ewaybill_type.py
+++ b/addons/l10n_in_edi_ewaybill/models/ewaybill_type.py
@@ -22,11 +22,7 @@ class EWayBillType(models.Model):
)
active = fields.Boolean("Active", default=True)
- def name_get(self):
+ def _compute_display_name(self):
"""Show name and sub_type in name"""
- result_dict = dict()
for ewaybill_type in self:
- name = ewaybill_type.name
- name += _(" (Sub-Type: %s)", ewaybill_type.sub_type)
- result_dict[ewaybill_type.id] = name
- return list(result_dict.items())
+ ewaybill_type.display_name = _("%s (Sub-Type: %s)", ewaybill_type.name, ewaybill_type.sub_type)
diff --git a/addons/l10n_it_edi/models/ddt.py b/addons/l10n_it_edi/models/ddt.py
index 1047e82303a..58ac4d2ee35 100644
--- a/addons/l10n_it_edi/models/ddt.py
+++ b/addons/l10n_it_edi/models/ddt.py
@@ -11,8 +11,6 @@ class L10nItDdt(models.Model):
name = fields.Char(string="Numero DDT", size=20, help="Transport document number", required=True)
date = fields.Date(string="Data DDT", help="Transport document date", required=True)
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for ddt in self:
- res.append((ddt.id, ("%s (%s)") % (ddt.name, ddt.date)))
- return res
+ ddt.display_name = f"{ddt.name} ({ddt.date})"
diff --git a/addons/l10n_latam_base/models/l10n_latam_identification_type.py b/addons/l10n_latam_base/models/l10n_latam_identification_type.py
index c893e61eacb..c6f873168c3 100644
--- a/addons/l10n_latam_base/models/l10n_latam_identification_type.py
+++ b/addons/l10n_latam_base/models/l10n_latam_identification_type.py
@@ -16,7 +16,7 @@ class L10nLatamIdentificationType(models.Model):
is_vat = fields.Boolean()
country_id = fields.Many2one('res.country')
- def name_get(self):
+ def _compute_display_name(self):
multi_localization = len(self.search([]).mapped('country_id')) > 1
- return [(rec.id, '%s%s' % (
- rec.name, multi_localization and rec.country_id and ' (%s)' % rec.country_id.code or '')) for rec in self]
+ for rec in self:
+ rec.display_name = '{}{}'.format(rec.name, multi_localization and rec.country_id and ' (%s)' % rec.country_id.code or '')
diff --git a/addons/l10n_latam_check/models/account_payment.py b/addons/l10n_latam_check/models/account_payment.py
index e5d76a5377c..5db65694895 100644
--- a/addons/l10n_latam_check/models/account_payment.py
+++ b/addons/l10n_latam_check/models/account_payment.py
@@ -283,13 +283,12 @@ class AccountPayment(models.Model):
})
return res
- def name_get(self):
+ def _compute_display_name(self):
""" Add check number to display_name on check_id m2o field """
- res_names = super().name_get()
- for i, (res_name, rec) in enumerate(zip(res_names, self)):
+ super()._compute_display_name()
+ for rec in self:
if rec.check_number and rec.payment_method_line_id.code == 'new_third_party_checks':
- res_names[i] = (res_name[0], "%s %s" % (res_name[1], _("(Check %s)", rec.check_number)))
- return res_names
+ rec.display_name = "{} {}".format(rec.display_name, _("(Check %s)", rec.check_number))
def button_open_check_operations(self):
''' Redirect the user to the invoice(s) paid by this payment.
diff --git a/addons/l10n_latam_invoice_document/models/l10n_latam_document_type.py b/addons/l10n_latam_invoice_document/models/l10n_latam_document_type.py
index d4aaf288afd..d208db5a6af 100644
--- a/addons/l10n_latam_invoice_document/models/l10n_latam_document_type.py
+++ b/addons/l10n_latam_invoice_document/models/l10n_latam_document_type.py
@@ -35,11 +35,9 @@ class L10nLatamDocumentType(models.Model):
self.ensure_one()
return document_number
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for rec in self:
name = rec.name
if rec.code:
- name = '(%s) %s' % (rec.code, name)
- result.append((rec.id, name))
- return result
+ name = f'({rec.code}) {name}'
+ rec.display_name = name
diff --git a/addons/loyalty/models/loyalty_card.py b/addons/loyalty/models/loyalty_card.py
index 893980bfc4e..9fe01f30bc4 100644
--- a/addons/loyalty/models/loyalty_card.py
+++ b/addons/loyalty/models/loyalty_card.py
@@ -19,8 +19,9 @@ class LoyaltyCard(models.Model):
"""
return '044' + str(uuid4())[7:-18]
- def name_get(self):
- return [(card.id, f'{card.program_id.name}: {card.code}') for card in self]
+ def _compute_display_name(self):
+ for card in self:
+ card.display_name = f'{card.program_id.name}: {card.code}'
program_id = fields.Many2one('loyalty.program', ondelete='restrict', default=lambda self: self.env.context.get('active_id', None))
program_type = fields.Selection(related='program_id.program_type')
diff --git a/addons/loyalty/models/loyalty_reward.py b/addons/loyalty/models/loyalty_reward.py
index b19a4f62c14..b77c502be31 100644
--- a/addons/loyalty/models/loyalty_reward.py
+++ b/addons/loyalty/models/loyalty_reward.py
@@ -38,8 +38,9 @@ class LoyaltyReward(models.Model):
('per_order', _('%s per order', symbol))
]
- def name_get(self):
- return [(reward.id, '%s - %s' % (reward.program_id.name, reward.description)) for reward in self]
+ def _compute_display_name(self):
+ for reward in self:
+ reward.display_name = f'{reward.program_id.name} - {reward.description}'
active = fields.Boolean(default=True)
program_id = fields.Many2one('loyalty.program', required=True, ondelete='cascade')
diff --git a/addons/lunch/models/lunch_cashmove.py b/addons/lunch/models/lunch_cashmove.py
index a0125ac4073..83761121f9e 100644
--- a/addons/lunch/models/lunch_cashmove.py
+++ b/addons/lunch/models/lunch_cashmove.py
@@ -18,8 +18,9 @@ class LunchCashMove(models.Model):
amount = fields.Float('Amount', required=True)
description = fields.Text('Description')
- def name_get(self):
- return [(cashmove.id, '%s %s' % (_('Lunch Cashmove'), '#%d' % cashmove.id)) for cashmove in self]
+ def _compute_display_name(self):
+ for cashmove in self:
+ cashmove.display_name = '{} {}'.format(_('Lunch Cashmove'), '#%d' % cashmove.id)
@api.model
def get_wallet_balance(self, user, include_config=True):
diff --git a/addons/lunch/models/lunch_supplier.py b/addons/lunch/models/lunch_supplier.py
index a0330eba77a..589c5d6a568 100644
--- a/addons/lunch/models/lunch_supplier.py
+++ b/addons/lunch/models/lunch_supplier.py
@@ -117,14 +117,12 @@ class LunchSupplier(models.Model):
'Automatic Email Sending Time should be between 0 and 12'),
]
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for supplier in self:
if supplier.phone:
- res.append((supplier.id, '%s %s' % (supplier.name, supplier.phone)))
+ supplier.display_name = f'{supplier.name} {supplier.phone}'
else:
- res.append((supplier.id, supplier.name))
- return res
+ supplier.display_name = supplier.name
def _sync_cron(self):
for supplier in self:
diff --git a/addons/lunch/models/lunch_topping.py b/addons/lunch/models/lunch_topping.py
index c7d6741672d..518f46661c0 100644
--- a/addons/lunch/models/lunch_topping.py
+++ b/addons/lunch/models/lunch_topping.py
@@ -17,10 +17,8 @@ class LunchTopping(models.Model):
supplier_id = fields.Many2one('lunch.supplier', ondelete='cascade')
topping_category = fields.Integer('Topping Category', required=True, default=1)
- def name_get(self):
+ def _compute_display_name(self):
currency_id = self.env.company.currency_id
- res = dict(super(LunchTopping, self).name_get())
for topping in self:
price = formatLang(self.env, topping.price, currency_obj=currency_id)
- res[topping.id] = '%s %s' % (topping.name, price)
- return list(res.items())
+ topping.display_name = f'{topping.name} {price}'
diff --git a/addons/lunch/report/lunch_cashmove_report.py b/addons/lunch/report/lunch_cashmove_report.py
index a45d66da916..1f7d7728c1d 100644
--- a/addons/lunch/report/lunch_cashmove_report.py
+++ b/addons/lunch/report/lunch_cashmove_report.py
@@ -17,8 +17,9 @@ class CashmoveReport(models.Model):
user_id = fields.Many2one('res.users', string='User')
description = fields.Text('Description')
- def name_get(self):
- return [(cashmove.id, '%s %s' % (_('Lunch Cashmove'), '#%d' % cashmove.id)) for cashmove in self]
+ def _compute_display_name(self):
+ for cashmove in self:
+ cashmove.display_name = '{} {}'.format(_('Lunch Cashmove'), '#%d' % cashmove.id)
def init(self):
tools.drop_view_if_exists(self._cr, self._table)
diff --git a/addons/mail/models/discuss/discuss_channel_member.py b/addons/mail/models/discuss/discuss_channel_member.py
index 93312e7f459..8d5714963da 100644
--- a/addons/mail/models/discuss/discuss_channel_member.py
+++ b/addons/mail/models/discuss/discuss_channel_member.py
@@ -59,8 +59,9 @@ class ChannelMember(models.Model):
else:
self.message_unread_counter = 0
- def name_get(self):
- return [(record.id, record.partner_id.name or record.guest_id.name) for record in self]
+ def _compute_display_name(self):
+ for record in self:
+ record.display_name = record.partner_id.name or record.guest_id.name
def init(self):
self.env.cr.execute("CREATE UNIQUE INDEX IF NOT EXISTS discuss_channel_member_partner_unique ON %s (channel_id, partner_id) WHERE partner_id IS NOT NULL" % self._table)
diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py
index c82b0bec848..dcd4352a09f 100644
--- a/addons/mail/models/mail_activity.py
+++ b/addons/mail/models/mail_activity.py
@@ -404,12 +404,10 @@ class MailActivity(models.Model):
)
return activities._as_query(order)
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for record in self:
name = record.summary or record.activity_type_id.display_name
- res.append((record.id, name))
- return res
+ record.display_name = name
# ------------------------------------------------------
# Business Methods
diff --git a/addons/mail/models/mail_alias.py b/addons/mail/models/mail_alias.py
index 1152f85a70d..e81d64a31db 100644
--- a/addons/mail/models/mail_alias.py
+++ b/addons/mail/models/mail_alias.py
@@ -147,20 +147,18 @@ class Alias(models.Model):
vals['alias_name'] = self._clean_and_check_unique([vals.get('alias_name')])[0]
return super(Alias, self).write(vals)
- def name_get(self):
+ def _compute_display_name(self):
"""Return the mail alias display alias_name, including the implicit
mail catchall domain if exists from config otherwise "New Alias".
e.g. `jobs@mail.odoo.com` or `jobs` or 'New Alias'
"""
- res = []
for record in self:
if record.alias_name and record.alias_domain:
- res.append((record['id'], "%s@%s" % (record.alias_name, record.alias_domain)))
+ record.display_name = f"{record.alias_name}@{record.alias_domain}"
elif record.alias_name:
- res.append((record['id'], "%s" % (record.alias_name)))
+ record.display_name = record.alias_name
else:
- res.append((record['id'], _("Inactive Alias")))
- return res
+ record.display_name = _("Inactive Alias")
def _clean_and_check_unique(self, names):
"""When an alias name appears to already be an email, we keep the local
diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py
index 584c432a6cb..ba37a2c7186 100644
--- a/addons/mail/models/mail_message.py
+++ b/addons/mail/models/mail_message.py
@@ -103,7 +103,7 @@ class Message(models.Model):
# related document
model = fields.Char('Related Document Model')
res_id = fields.Many2oneReference('Related Document ID', model_field='model')
- record_name = fields.Char('Message Record Name') # name_get() of the related document
+ record_name = fields.Char('Message Record Name') # display_name of the related document
link_preview_ids = fields.One2many('mail.link.preview', 'message_id', string='Link Previews', groups="base.group_erp_manager")
# characteristics
message_type = fields.Selection([
@@ -993,7 +993,7 @@ class Message(models.Model):
'email_from': 'sacha@pokemon.com' # email address or False
'subtype_id': (1, u'Discussions'),
'date': '2015-06-30 08:22:33',
- 'partner_ids': [[7, "Sacha Du Bourg-Palette"]], # list of partner name_get
+ 'partner_ids': [[7, "Sacha Du Bourg-Palette"]], # list of partner convert_to_read
'message_type': u'comment',
'id': 59,
'subject': False
@@ -1194,7 +1194,7 @@ class Message(models.Model):
@api.model
def _get_record_name(self, values):
- """ Return the related document name, using name_get. It is done using
+ """ Return the related document name, using display_name. It is done using
SUPERUSER_ID, to be sure to have the record name correctly stored. """
model = values.get('model', self.env.context.get('default_model'))
res_id = values.get('res_id', self.env.context.get('default_res_id'))
diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py
index 629fcded8dd..a72af6e9a36 100644
--- a/addons/mail/models/mail_thread.py
+++ b/addons/mail/models/mail_thread.py
@@ -2712,7 +2712,7 @@ class MailThread(models.AbstractModel):
:return str: default subject """
self.ensure_one()
- return self.name_get()[0][1]
+ return self.display_name
def _message_create(self, values_list):
""" Low-level helper to create mail.message records. It is mainly used
diff --git a/addons/mail/models/mail_tracking_value.py b/addons/mail/models/mail_tracking_value.py
index 89945a5a803..2c3ccf2e524 100644
--- a/addons/mail/models/mail_tracking_value.py
+++ b/addons/mail/models/mail_tracking_value.py
@@ -78,8 +78,8 @@ class MailTracking(models.Model):
values.update({
'old_value_integer': initial_value and initial_value.id or 0,
'new_value_integer': new_value and new_value.id or 0,
- 'old_value_char': initial_value and initial_value.sudo().name_get()[0][1] or '',
- 'new_value_char': new_value and new_value.sudo().name_get()[0][1] or ''
+ 'old_value_char': initial_value and initial_value.sudo().display_name or '',
+ 'new_value_char': new_value and new_value.sudo().display_name or ''
})
elif col_info['type'] in ['many2many', 'one2many']:
values.update({
diff --git a/addons/mail/models/res_users_settings_volumes.py b/addons/mail/models/res_users_settings_volumes.py
index 7d9bde64556..c2c4f0f0ef3 100644
--- a/addons/mail/models/res_users_settings_volumes.py
+++ b/addons/mail/models/res_users_settings_volumes.py
@@ -22,8 +22,9 @@ class ResUsersSettingsVolumes(models.Model):
("partner_or_guest_exists", "CHECK((partner_id IS NOT NULL AND guest_id IS NULL) OR (partner_id IS NULL AND guest_id IS NOT NULL))", "A volume setting must have a partner or a guest."),
]
- def name_get(self):
- return [(rec.id, f'{rec.user_setting_id.user_id.name} - {rec.partner_id.name or rec.guest_id.name}') for rec in self]
+ def _compute_display_name(self):
+ for rec in self:
+ rec.display_name = f'{rec.user_setting_id.user_id.name} - {rec.partner_id.name or rec.guest_id.name}'
def _discuss_users_settings_volume_format(self):
return [{
diff --git a/addons/mail/static/src/core/web/message_patch.js b/addons/mail/static/src/core/web/message_patch.js
index e68488c9bbf..62b9074d11b 100644
--- a/addons/mail/static/src/core/web/message_patch.js
+++ b/addons/mail/static/src/core/web/message_patch.js
@@ -60,7 +60,7 @@ patch(Message.prototype, "mail/core/web", {
case "boolean":
return trackingValue.value ? _t("Yes") : _t("No");
/**
- * many2one formatter exists but is expecting id/name_get or data
+ * many2one formatter exists but is expecting id/display_name or data
* object but only the target record name is known in this context.
*
* Selection formatter exists but requires knowing all
diff --git a/addons/mail_plugin/controllers/mail_plugin.py b/addons/mail_plugin/controllers/mail_plugin.py
index 4ca6c7e426f..a163a4a4edc 100644
--- a/addons/mail_plugin/controllers/mail_plugin.py
+++ b/addons/mail_plugin/controllers/mail_plugin.py
@@ -193,7 +193,7 @@ class MailPluginController(http.Controller):
if normalized_email:
filter_domain = [('email_normalized', 'ilike', search_term)]
else:
- filter_domain = ['|', '|', ('display_name', 'ilike', search_term), ('ref', '=', search_term),
+ filter_domain = ['|', '|', ('complete_name', 'ilike', search_term), ('ref', '=', search_term),
('email', 'ilike', search_term)]
# Search for the partner based on the email.
diff --git a/addons/maintenance/models/maintenance.py b/addons/maintenance/models/maintenance.py
index a6441d64aaa..d90f846f7ae 100644
--- a/addons/maintenance/models/maintenance.py
+++ b/addons/maintenance/models/maintenance.py
@@ -92,14 +92,12 @@ class MaintenanceEquipment(models.Model):
return self.env.ref('maintenance.mt_mat_assign')
return super(MaintenanceEquipment, self)._track_subtype(init_values)
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for record in self:
if record.name and record.serial_no:
- result.append((record.id, record.name + '/' + record.serial_no))
+ record.display_name = record.name + '/' + record.serial_no
if record.name and not record.serial_no:
- result.append((record.id, record.name))
- return result
+ record.display_name = record.name
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
diff --git a/addons/mass_mailing/models/mailing_contact.py b/addons/mass_mailing/models/mailing_contact.py
index 21933b40f36..d94b8bf9fe7 100644
--- a/addons/mass_mailing/models/mailing_contact.py
+++ b/addons/mass_mailing/models/mailing_contact.py
@@ -129,13 +129,13 @@ class MassMailingContact(models.Model):
def name_create(self, name):
name, email = self.get_name_email(name)
contact = self.create({'name': name, 'email': email})
- return contact.name_get()[0]
+ return contact.id, contact.display_name
@api.model
def add_to_list(self, name, list_id):
name, email = self.get_name_email(name)
contact = self.create({'name': name, 'email': email, 'list_ids': [(4, list_id)]})
- return contact.name_get()[0]
+ return contact.id, contact.display_name
def _message_get_default_recipients(self):
return {r.id: {
diff --git a/addons/mass_mailing/models/mailing_list.py b/addons/mass_mailing/models/mailing_list.py
index e6f3de9f8f9..e2585c5bddf 100644
--- a/addons/mass_mailing/models/mailing_list.py
+++ b/addons/mass_mailing/models/mailing_list.py
@@ -120,8 +120,9 @@ class MassMailingList(models.Model):
return super(MassMailingList, self).write(vals)
- def name_get(self):
- return [(list.id, "%s (%s)" % (list.name, list.contact_count)) for list in self]
+ def _compute_display_name(self):
+ for mailing_list in self:
+ mailing_list.display_name = f"{mailing_list.name} ({mailing_list.contact_count})"
def copy(self, default=None):
self.ensure_one()
diff --git a/addons/mass_mailing/models/mailing_trace.py b/addons/mass_mailing/models/mailing_trace.py
index 9fa467177bc..cf0f2fd1380 100644
--- a/addons/mass_mailing/models/mailing_trace.py
+++ b/addons/mass_mailing/models/mailing_trace.py
@@ -52,7 +52,6 @@ class MailingTrace(models.Model):
_order = 'create_date DESC'
trace_type = fields.Selection([('mail', 'Email')], string='Type', default='mail', required=True)
- display_name = fields.Char(compute='_compute_display_name')
# mail data
mail_mail_id = fields.Many2one('mail.mail', string='Mail', index='btree_not_null')
mail_mail_id_int = fields.Integer(
@@ -117,7 +116,7 @@ class MailingTrace(models.Model):
@api.depends('trace_type', 'mass_mailing_id')
def _compute_display_name(self):
for trace in self:
- trace.display_name = '%s: %s (%s)' % (trace.trace_type, trace.mass_mailing_id.name, trace.id)
+ trace.display_name = f'{trace.trace_type}: {trace.mass_mailing_id.name} ({trace.id})'
@api.model_create_multi
def create(self, values_list):
diff --git a/addons/mrp/models/mrp_bom.py b/addons/mrp/models/mrp_bom.py
index 1f7a51d4fa1..878183f36c6 100644
--- a/addons/mrp/models/mrp_bom.py
+++ b/addons/mrp/models/mrp_bom.py
@@ -253,8 +253,9 @@ class MrpBom(models.Model):
self.with_context({'active_test': False}).operation_ids.toggle_active()
return super().toggle_active()
- def name_get(self):
- return [(bom.id, '%s%s' % (bom.code and '%s: ' % bom.code or '', bom.product_tmpl_id.display_name)) for bom in self]
+ def _compute_display_name(self):
+ for bom in self:
+ bom.display_name = f"{bom.code + ': ' if bom.code else ''}{bom.product_tmpl_id.display_name}"
def action_compute_bom_days(self):
company_id = self.env.context.get('default_company_id', self.env.company.id)
diff --git a/addons/mrp/models/mrp_workcenter.py b/addons/mrp/models/mrp_workcenter.py
index 58a97df5578..a6cb798f5fd 100644
--- a/addons/mrp/models/mrp_workcenter.py
+++ b/addons/mrp/models/mrp_workcenter.py
@@ -328,15 +328,13 @@ class MrpWorkcenterProductivityLossType(models.Model):
_rec_name = 'loss_type'
@api.depends('loss_type')
- def name_get(self):
+ def _compute_display_name(self):
""" As 'category' field in form view is a Many2one, its value will be in
- lower case. In order to display its value capitalized 'name_get' is
+ lower case. In order to display its value capitalized 'display_name' is
overrided.
"""
- result = []
for rec in self:
- result.append((rec.id, rec.loss_type.title()))
- return result
+ rec.display_name = rec.loss_type.title()
loss_type = fields.Selection([
('availability', 'Availability'),
diff --git a/addons/mrp/models/mrp_workorder.py b/addons/mrp/models/mrp_workorder.py
index 32561266444..26fad8d089b 100644
--- a/addons/mrp/models/mrp_workorder.py
+++ b/addons/mrp/models/mrp_workorder.py
@@ -272,14 +272,12 @@ class MrpWorkorder(models.Model):
if not self._check_m2m_recursion('blocked_by_workorder_ids'):
raise ValidationError(_("You cannot create cyclic dependency."))
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for wo in self:
if len(wo.production_id.workorder_ids) == 1:
- res.append((wo.id, "%s - %s - %s" % (wo.production_id.name, wo.product_id.name, wo.name)))
+ wo.display_name = f"{wo.production_id.name} - {wo.product_id.name} - {wo.name}"
else:
- res.append((wo.id, "%s - %s - %s - %s" % (wo.production_id.workorder_ids.ids.index(wo._origin.id) + 1, wo.production_id.name, wo.product_id.name, wo.name)))
- return res
+ wo.display_name = f"{wo.production_id.workorder_ids.ids.index(wo._origin.id) + 1} - {wo.production_id.name} - {wo.product_id.name} - {wo.name}"
def unlink(self):
# Removes references to workorder to avoid Validation Error
diff --git a/addons/mrp_subcontracting/models/mrp_production.py b/addons/mrp_subcontracting/models/mrp_production.py
index 4bd5940f77b..a9ab62ef40c 100644
--- a/addons/mrp_subcontracting/models/mrp_production.py
+++ b/addons/mrp_subcontracting/models/mrp_production.py
@@ -21,13 +21,6 @@ class MrpProduction(models.Model):
incoming_picking = fields.Many2one(related='move_finished_ids.move_dest_ids.picking_id')
- @api.depends('name')
- def name_get(self):
- return [
- (record.id, "%s (%s)" % (record.incoming_picking.name, record.name)) if record.bom_id.type == 'subcontract'
- else (record.id, record.name) for record in self
- ]
-
@api.depends('move_raw_ids.move_line_ids')
def _compute_move_line_raw_ids(self):
for production in self:
diff --git a/addons/partner_autocomplete/models/res_company.py b/addons/partner_autocomplete/models/res_company.py
index b2c52162548..742cbdf6d66 100644
--- a/addons/partner_autocomplete/models/res_company.py
+++ b/addons/partner_autocomplete/models/res_company.py
@@ -65,7 +65,7 @@ class ResCompany(models.Model):
company_data = {field: value for field, value in company_data.items()
if field in self.partner_id._fields and value and (field == 'image_1920' or not self.partner_id[field])}
- # for company and childs: from state_id / country_id name_get like to IDs
+ # for company and childs: from state_id / country_id display_name like to IDs
company_data.update(self._enrich_extract_m2o_id(company_data, ['state_id', 'country_id']))
if company_data.get('child_ids'):
company_data['child_ids'] = [
diff --git a/addons/payment/models/payment_token.py b/addons/payment/models/payment_token.py
index 1450e89b907..4acad1c76b7 100644
--- a/addons/payment/models/payment_token.py
+++ b/addons/payment/models/payment_token.py
@@ -27,6 +27,12 @@ class PaymentToken(models.Model):
verified = fields.Boolean(string="Verified")
active = fields.Boolean(string="Active", default=True)
+ #=== COMPUTE METHODS ===#
+
+ def _compute_display_name(self):
+ for token in self:
+ token.display_name = token._build_display_name()
+
#=== CRUD METHODS ===#
@api.model_create_multi
@@ -91,9 +97,6 @@ class PaymentToken(models.Model):
"""
return
- def name_get(self):
- return [(token.id, token._build_display_name()) for token in self]
-
#=== BUSINESS METHODS ===#
def _get_available_tokens(self, providers_ids, partner_id, is_validation=False, **kwargs):
diff --git a/addons/payment/wizards/payment_link_wizard.py b/addons/payment/wizards/payment_link_wizard.py
index 11ef8e6d4c6..69581b73f98 100644
--- a/addons/payment/wizards/payment_link_wizard.py
+++ b/addons/payment/wizards/payment_link_wizard.py
@@ -100,14 +100,15 @@ class PaymentLinkWizard(models.TransientModel):
partner_id = related_document.partner_id
currency_id = related_document.currency_id
selection.extend(
- self._get_payment_provider_available(
+ (payment_provider.id, payment_provider.display_name)
+ for payment_provider in self._get_payment_provider_available(
res_model=res_model,
res_id=res_id,
company_id=company_id.id,
partner_id=partner_id.id,
amount=related_document.amount_total,
currency_id=currency_id.id,
- ).name_get()
+ )
)
return selection
diff --git a/addons/point_of_sale/models/pos_bill.py b/addons/point_of_sale/models/pos_bill.py
index 87d17c784a8..36caa48ad98 100644
--- a/addons/point_of_sale/models/pos_bill.py
+++ b/addons/point_of_sale/models/pos_bill.py
@@ -15,7 +15,7 @@ class Bill(models.Model):
def name_create(self, name):
try:
value = float(name)
- except:
+ except ValueError:
raise UserError(_("The name of the Coins/Bills must be a number."))
result = super().create({"name": name, "value": value})
- return result.name_get()[0]
+ return result.id, result.display_name
diff --git a/addons/point_of_sale/models/pos_category.py b/addons/point_of_sale/models/pos_category.py
index 31bf309ed4d..ab79e2ac36a 100644
--- a/addons/point_of_sale/models/pos_category.py
+++ b/addons/point_of_sale/models/pos_category.py
@@ -32,8 +32,9 @@ class PosCategory(models.Model):
self.ensure_one()
return (self.parent_id._get_hierarchy() if self.parent_id else []) + [self.name]
- def name_get(self) -> List[Tuple[int, str]]:
- return [(category.id, " / ".join(category._get_hierarchy())) for category in self if category.name]
+ def _compute_display_name(self):
+ for cat in self:
+ cat.display_name = " / ".join(cat._get_hierarchy())
@api.ondelete(at_uninstall=False)
def _unlink_except_session_open(self):
diff --git a/addons/point_of_sale/models/pos_config.py b/addons/point_of_sale/models/pos_config.py
index a5d6f18c91c..51530d93cb3 100644
--- a/addons/point_of_sale/models/pos_config.py
+++ b/addons/point_of_sale/models/pos_config.py
@@ -366,15 +366,13 @@ class PosConfig(models.Model):
if trusted_config.currency_id != config.currency_id:
raise ValidationError(_("You cannot share open orders with configuration that does not use the same currency."))
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for config in self:
last_session = self.env['pos.session'].search([('config_id', '=', config.id)], limit=1)
if (not last_session) or (last_session.state == 'closed'):
- result.append((config.id, _("%(pos_name)s (not used)", pos_name=config.name)))
+ config.display_name = _("%(pos_name)s (not used)", pos_name=config.name)
else:
- result.append((config.id, "%s (%s)" % (config.name, last_session.user_id.name)))
- return result
+ config.display_name = f"{config.name} ({last_session.user_id.name})"
@api.model_create_multi
def create(self, vals_list):
diff --git a/addons/point_of_sale/models/pos_payment.py b/addons/point_of_sale/models/pos_payment.py
index b3e9b6bf305..ad2bf1648b7 100644
--- a/addons/point_of_sale/models/pos_payment.py
+++ b/addons/point_of_sale/models/pos_payment.py
@@ -33,14 +33,12 @@ class PosPayment(models.Model):
is_change = fields.Boolean(string='Is this payment change?', default=False)
account_move_id = fields.Many2one('account.move')
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for payment in self:
if payment.name:
- res.append((payment.id, '%s %s' % (payment.name, formatLang(self.env, payment.amount, currency_obj=payment.currency_id))))
+ payment.display_name = f'{payment.name} {formatLang(self.env, payment.amount, currency_obj=payment.currency_id)}'
else:
- res.append((payment.id, formatLang(self.env, payment.amount, currency_obj=payment.currency_id)))
- return res
+ payment.display_name = formatLang(self.env, payment.amount, currency_obj=payment.currency_id)
@api.constrains('payment_method_id')
def _check_payment_method_id(self):
diff --git a/addons/point_of_sale/static/src/app/screens/ticket_screen/ticket_screen.js b/addons/point_of_sale/static/src/app/screens/ticket_screen/ticket_screen.js
index 4a395b38f61..fdc322a8b28 100644
--- a/addons/point_of_sale/static/src/app/screens/ticket_screen/ticket_screen.js
+++ b/addons/point_of_sale/static/src/app/screens/ticket_screen/ticket_screen.js
@@ -587,7 +587,7 @@ export class TicketScreen extends Component {
PARTNER: {
repr: (order) => order.get_partner_name(),
displayName: this.env._t("Customer"),
- modelField: "partner_id.display_name",
+ modelField: "partner_id.complete_name",
},
};
diff --git a/addons/pos_sale/static/src/js/OrderManagementScreen/SaleOrderManagementControlPanel.js b/addons/pos_sale/static/src/js/OrderManagementScreen/SaleOrderManagementControlPanel.js
index 0d8f51bc186..89f4b1acd7f 100644
--- a/addons/pos_sale/static/src/js/OrderManagementScreen/SaleOrderManagementControlPanel.js
+++ b/addons/pos_sale/static/src/js/OrderManagementScreen/SaleOrderManagementControlPanel.js
@@ -9,12 +9,12 @@ import { usePos } from "@point_of_sale/app/store/pos_hook";
const VALID_SEARCH_TAGS = new Set(["date", "customer", "client", "name", "order"]);
const FIELD_MAP = {
date: "date_order",
- customer: "partner_id.display_name",
- client: "partner_id.display_name",
+ customer: "partner_id.complete_name",
+ client: "partner_id.complete_name",
name: "name",
order: "name",
};
-const SEARCH_FIELDS = ["name", "partner_id.display_name", "date_order"];
+const SEARCH_FIELDS = ["name", "partner_id.complete_name", "date_order"];
/**
* @emits search
@@ -64,7 +64,7 @@ export class SaleOrderManagementControlPanel extends Component {
* '|',
* '|',
* ['pos_reference', 'ilike', '%Customer 1%'],
- * ['partner_id.display_name', 'ilike', '%Customer 1%'],
+ * ['partner_id.complete_name', 'ilike', '%Customer 1%'],
* ['date_order', 'ilike', '%Customer 1%']
* ]
* ```
@@ -81,7 +81,7 @@ export class SaleOrderManagementControlPanel extends Component {
* ```
* searchString = 'customer: Steward, date: 2020-05-01'
* result = [
- * ['partner_id.display_name', 'ilike', '%Steward%'],
+ * ['partner_id.complete_name', 'ilike', '%Steward%'],
* ['date_order', 'ilike', '%2020-05-01%']
* ]
* ```
diff --git a/addons/privacy_lookup/wizard/privacy_lookup_wizard.py b/addons/privacy_lookup/wizard/privacy_lookup_wizard.py
index 6a63e6608f8..cc5ffbbd769 100644
--- a/addons/privacy_lookup/wizard/privacy_lookup_wizard.py
+++ b/addons/privacy_lookup/wizard/privacy_lookup_wizard.py
@@ -27,8 +27,8 @@ class PrivacyLookupWizard(models.TransientModel):
for wizard in self:
wizard.line_count = len(wizard.line_ids)
- def name_get(self):
- return [(w.id, _('Privacy Lookup')) for w in self]
+ def _compute_display_name(self):
+ self.display_name = _('Privacy Lookup')
def _get_query_models_blacklist(self):
return [
@@ -286,8 +286,8 @@ class PrivacyLookupWizardLine(models.TransientModel):
record = self.env[line.res_model].sudo().browse(line.res_id)
if not record.exists():
continue
- name = record.name_get()
- line.res_name = name[0][1] if name else ('%s/%s') % (line.res_model_id.name, line.res_id)
+ name = record.display_name
+ line.res_name = name if name else f'{line.res_model_id.name}/{line.res_id}'
@api.onchange('is_active')
def _onchange_is_active(self):
diff --git a/addons/product/models/product_attribute_value.py b/addons/product/models/product_attribute_value.py
index b0a050a7ce9..eed67e0d9e8 100644
--- a/addons/product/models/product_attribute_value.py
+++ b/addons/product/models/product_attribute_value.py
@@ -55,7 +55,7 @@ class ProductAttributeValue(models.Model):
for pav in self:
pav.is_used_on_products = bool(pav.pav_attribute_line_ids)
- def name_get(self):
+ def _compute_display_name(self):
"""Override because in general the name of the value is confusing if it
is displayed without the name of the corresponding attribute.
Eg. on product list & kanban views, on BOM form view
@@ -65,8 +65,9 @@ class ProductAttributeValue(models.Model):
on every value.
"""
if not self.env.context.get('show_attribute', True):
- return super().name_get()
- return [(value.id, "%s: %s" % (value.attribute_id.name, value.name)) for value in self]
+ return super()._compute_display_name()
+ for value in self:
+ value.display_name = f"{value.attribute_id.name}: {value.name}"
def write(self, values):
if 'attribute_id' in values:
diff --git a/addons/product/models/product_category.py b/addons/product/models/product_category.py
index 1c16e963a5b..59e976b9d4e 100644
--- a/addons/product/models/product_category.py
+++ b/addons/product/models/product_category.py
@@ -48,12 +48,14 @@ class ProductCategory(models.Model):
@api.model
def name_create(self, name):
- return self.create({'name': name}).name_get()[0]
+ category = self.create({'name': name})
+ return category.id, category.display_name
- def name_get(self):
- if not self.env.context.get('hierarchical_naming', True):
- return [(record.id, record.name) for record in self]
- return super().name_get()
+ def _compute_display_name(self):
+ if self.env.context.get('hierarchical_naming', True):
+ return super()._compute_display_name()
+ for record in self:
+ record.display_name = record.name
@api.ondelete(at_uninstall=False)
def _unlink_except_default_category(self):
diff --git a/addons/product/models/product_pricelist.py b/addons/product/models/product_pricelist.py
index 9acad80871d..87123044943 100644
--- a/addons/product/models/product_pricelist.py
+++ b/addons/product/models/product_pricelist.py
@@ -64,8 +64,9 @@ class Pricelist(models.Model):
],
copy=True)
- def name_get(self):
- return [(pricelist.id, '%s (%s)' % (pricelist.name, pricelist.currency_id.name)) for pricelist in self]
+ def _compute_display_name(self):
+ for pricelist in self:
+ pricelist.display_name = f'{pricelist.name} ({pricelist.currency_id.name})'
def _get_products_price(self, products, *args, **kwargs):
"""Compute the pricelist prices for the specified products, quantity & uom.
diff --git a/addons/product/models/product_product.py b/addons/product/models/product_product.py
index d2fb084846b..dee7e5a62e8 100644
--- a/addons/product/models/product_product.py
+++ b/addons/product/models/product_product.py
@@ -8,6 +8,7 @@ from odoo import api, fields, models, tools, _
from odoo.exceptions import ValidationError
from odoo.osv import expression
from odoo.tools import float_compare
+from odoo.tools.misc import unique
class ProductProduct(models.Model):
@@ -415,21 +416,13 @@ class ProductProduct(models.Model):
domain.append((('categ_id', 'child_of', self._context['search_default_categ_id'])))
return super()._search(domain, offset, limit, order, access_rights_uid)
- @api.depends_context('display_default_code', 'seller_id')
+ @api.depends_context('display_default_code', 'seller_id', 'company_id')
def _compute_display_name(self):
- # `display_name` is calling `name_get()`` which is overidden on product
- # to depend on `display_default_code` and `seller_id`
- return super()._compute_display_name()
- def name_get(self):
- # TDE: this could be cleaned a bit I think
-
- def _name_get(d):
- name = d.get('name', '')
- code = self._context.get('display_default_code', True) and d.get('default_code', False) or False
- if code:
- name = '[%s] %s' % (code,name)
- return (d['id'], name)
+ def get_display_name(name, code):
+ if self._context.get('display_default_code', True) and code:
+ return f'[{code}] {name}'
+ return name
partner_id = self._context.get('partner_id')
if partner_id:
@@ -443,15 +436,13 @@ class ProductProduct(models.Model):
self.check_access_rights("read")
self.check_access_rule("read")
- result = []
-
- # prefetch the fields used by the `name_get`
+ # prefetch the fields used by the `display_name`
self.sudo().fetch(['name', 'default_code', 'product_tmpl_id'])
product_template_ids = self.sudo().product_tmpl_id.ids
if partner_ids:
- # prefetch the fields used by the `name_get`
+ # prefetch the fields used by the `display_name`
supplier_info = self.env['product.supplierinfo'].sudo().search_fetch(
[('product_tmpl_id', 'in', product_template_ids), ('partner_id', 'in', partner_ids)],
['product_tmpl_id', 'product_id', 'company_id', 'product_name', 'product_code'],
@@ -476,27 +467,18 @@ class ProductProduct(models.Model):
if company_id:
sellers = [x for x in sellers if x.company_id.id in [company_id, False]]
if sellers:
+ temp = []
for s in sellers:
seller_variant = s.product_name and (
variant and "%s (%s)" % (s.product_name, variant) or s.product_name
) or False
- mydict = {
- 'id': product.id,
- 'name': seller_variant or name,
- 'default_code': s.product_code or product.default_code,
- }
- temp = _name_get(mydict)
- if temp not in result:
- result.append(temp)
- else:
- mydict = {
- 'id': product.id,
- 'name': name,
- 'default_code': product.default_code,
- }
- result.append(_name_get(mydict))
+ temp.append(get_display_name(seller_variant or name, s.product_code or product.default_code))
- return result
+ # => Feature drop here, one record can only have one display_name now, instead separate with `,`
+ # Remove this comment
+ product.display_name = ", ".join(unique(temp))
+ else:
+ product.display_name = get_display_name(name, product.default_code)
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py
index 029d47379cd..f05f58d8ee1 100644
--- a/addons/product/models/product_template.py
+++ b/addons/product/models/product_template.py
@@ -485,11 +485,11 @@ class ProductTemplate(models.Model):
default['name'] = _("%s (copy)", self.name)
return super(ProductTemplate, self).copy(default=default)
- def name_get(self):
- # Prefetch the fields used by the `name_get`, so `browse` doesn't fetch other fields
+ def _compute_display_name(self):
+ # Prefetch the fields used by the `display_name`, so `browse` doesn't fetch other fields
self.fetch(['name', 'default_code'])
- return [(template.id, '%s%s' % (template.default_code and '[%s] ' % template.default_code or '', template.name))
- for template in self]
+ for template in self:
+ template.display_name = '{}{}'.format(template.default_code and '[%s] ' % template.default_code or '', template.name)
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
@@ -529,7 +529,7 @@ class ProductTemplate(models.Model):
domain2 = expression.AND([domain, [('id', 'in', tmpl_without_variant.ids)]])
searched_ids |= set(super()._name_search(name, domain2, operator, limit, order))
- # re-apply product.template order + name_get
+ # re-apply product.template order + display_name
domain = [('id', 'in', list(searched_ids))]
return super()._name_search('', domain, 'ilike', limit, order)
diff --git a/addons/product/models/product_template_attribute_value.py b/addons/product/models/product_template_attribute_value.py
index eea2dd5bab7..ebd6b3924ca 100644
--- a/addons/product/models/product_template_attribute_value.py
+++ b/addons/product/models/product_template_attribute_value.py
@@ -147,12 +147,13 @@ class ProductTemplateAttributeValue(models.Model):
ptav_to_archive.write({'ptav_active': False})
return True
- def name_get(self):
+ def _compute_display_name(self):
"""Override because in general the name of the value is confusing if it
is displayed without the name of the corresponding attribute.
Eg. on exclusion rules form
"""
- return [(value.id, "%s: %s" % (value.attribute_id.name, value.name)) for value in self]
+ for value in self:
+ value.display_name = f"{value.attribute_id.name}: {value.name}"
def _only_active(self):
return self.filtered(lambda ptav: ptav.ptav_active)
diff --git a/addons/product/tests/test_seller.py b/addons/product/tests/test_seller.py
index da3c495331f..41eb23c8e00 100644
--- a/addons/product/tests/test_seller.py
+++ b/addons/product/tests/test_seller.py
@@ -48,26 +48,20 @@ class TestSeller(TransactionCase):
(0, 0, {'partner_id': self.asustec.id, 'product_code': 'NO', 'company_id': False}),
]})
- names = self.product_consu.with_context(
+ name = self.product_consu.with_context(
partner_id=self.asustec.id,
- ).name_get()
- ref = set([x[1] for x in names])
- self.assertEqual(len(names), 3, "3 vendor references should have been found")
- self.assertEqual(ref, {'[A] Boudin', '[B] Boudin', '[NO] Boudin'}, "Incorrect vendor reference list")
- names = self.product_consu.with_context(
+ ).display_name
+ self.assertEqual(name, '[A] Boudin, [B] Boudin, [NO] Boudin', "Incorrect vendor reference list")
+ name = self.product_consu.with_context(
partner_id=self.asustec.id,
company_id=company_a.id,
- ).name_get()
- ref = set([x[1] for x in names])
- self.assertEqual(len(names), 2, "2 vendor references should have been found")
- self.assertEqual(ref, {'[A] Boudin', '[NO] Boudin'}, "Incorrect vendor reference list")
- names = self.product_consu.with_context(
+ ).display_name
+ self.assertEqual(name, '[A] Boudin, [NO] Boudin', "Incorrect vendor reference list")
+ name = self.product_consu.with_context(
partner_id=self.asustec.id,
company_id=company_b.id,
- ).name_get()
- ref = set([x[1] for x in names])
- self.assertEqual(len(names), 2, "2 vendor references should have been found")
- self.assertEqual(ref, {'[B] Boudin', '[NO] Boudin'}, "Incorrect vendor reference list")
+ ).display_name
+ self.assertEqual(name, '[B] Boudin, [NO] Boudin', "Incorrect vendor reference list")
def test_30_select_seller(self):
self.res_partner_1 = self.asustec
diff --git a/addons/project/models/project_collaborator.py b/addons/project/models/project_collaborator.py
index 5919f33da72..f39dd93e431 100644
--- a/addons/project/models/project_collaborator.py
+++ b/addons/project/models/project_collaborator.py
@@ -16,9 +16,10 @@ class ProjectCollaborator(models.Model):
('unique_collaborator', 'UNIQUE(project_id, partner_id)', 'A collaborator cannot be selected more than once in the project sharing access. Please remove duplicate(s) and try again.'),
]
- def name_get(self):
- collaborator_search_read = self.search_read([('id', 'in', self.ids)], ['id', 'project_id', 'partner_id'])
- return [(collaborator['id'], '%s - %s' % (collaborator['project_id'][1], collaborator['partner_id'][1])) for collaborator in collaborator_search_read]
+ def _compute_display_name(self):
+ self.fetch(['project_id', 'partner_id'])
+ for collaborator in self:
+ collaborator.display_name = f'{collaborator.project_id.display_name} - {collaborator.partner_id.display_name}'
@api.model_create_multi
def create(self, vals_list):
diff --git a/addons/project/models/project_tags.py b/addons/project/models/project_tags.py
index 1ab86ea6dc2..ea0a54c3cff 100644
--- a/addons/project/models/project_tags.py
+++ b/addons/project/models/project_tags.py
@@ -121,5 +121,5 @@ class ProjectTags(models.Model):
def name_create(self, name):
existing_tag = self.search([('name', '=ilike', name.strip())], limit=1)
if existing_tag:
- return existing_tag.name_get()[0]
+ return existing_tag.id, existing_tag.display_name
return super().name_create(name)
diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py
index 49924ebd1f6..78e04d69b1a 100644
--- a/addons/purchase/models/purchase.py
+++ b/addons/purchase/models/purchase.py
@@ -193,16 +193,14 @@ class PurchaseOrder(models.Model):
order.date_planned = False
@api.depends('name', 'partner_ref')
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for po in self:
name = po.name
if po.partner_ref:
name += ' (' + po.partner_ref + ')'
if self.env.context.get('show_total_amount') and po.amount_total:
name += ': ' + formatLang(self.env, po.amount_total, currency_obj=po.currency_id)
- result.append((po.id, name))
- return result
+ po.display_name = name
@api.depends('order_line.taxes_id', 'order_line.price_subtotal', 'amount_total', 'amount_untaxed')
def _compute_tax_totals(self):
diff --git a/addons/purchase/report/purchase_bill.py b/addons/purchase/report/purchase_bill.py
index 8ca87dfdaa7..4cb82f845e0 100644
--- a/addons/purchase/report/purchase_bill.py
+++ b/addons/purchase/report/purchase_bill.py
@@ -40,8 +40,7 @@ class PurchaseBillUnion(models.Model):
invoice_status in ('to invoice', 'no')
)""")
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for doc in self:
name = doc.name or ''
if doc.reference:
@@ -50,5 +49,4 @@ class PurchaseBillUnion(models.Model):
if doc.purchase_order_id and doc.purchase_order_id.invoice_status == 'no':
amount = 0.0
name += ': ' + formatLang(self.env, amount, monetary=True, currency_obj=doc.currency_id)
- result.append((doc.id, name))
- return result
+ doc.display_name = name
diff --git a/addons/rating/models/rating.py b/addons/rating/models/rating.py
index b47e04d751d..7b005fb929c 100644
--- a/addons/rating/models/rating.py
+++ b/addons/rating/models/rating.py
@@ -59,8 +59,8 @@ class Rating(models.Model):
@api.depends('res_model', 'res_id')
def _compute_res_name(self):
for rating in self:
- name = self.env[rating.res_model].sudo().browse(rating.res_id).name_get()
- rating.res_name = name and name[0][1] or ('%s/%s') % (rating.res_model, rating.res_id)
+ name = self.env[rating.res_model].sudo().browse(rating.res_id).display_name
+ rating.res_name = name or f'{rating.res_model}/{rating.res_id}'
@api.depends('res_model', 'res_id')
def _compute_resource_ref(self):
@@ -83,8 +83,8 @@ class Rating(models.Model):
for rating in self:
name = False
if rating.parent_res_model and rating.parent_res_id:
- name = self.env[rating.parent_res_model].sudo().browse(rating.parent_res_id).name_get()
- name = name and name[0][1] or ('%s/%s') % (rating.parent_res_model, rating.parent_res_id)
+ name = self.env[rating.parent_res_model].sudo().browse(rating.parent_res_id).display_name
+ name = name or f'{rating.parent_res_model}/{rating.parent_res_id}'
rating.parent_res_name = name
def _get_rating_image_filename(self):
diff --git a/addons/resource/models/resource_calendar_attendance.py b/addons/resource/models/resource_calendar_attendance.py
index 859673f5f8d..e8aa2552464 100644
--- a/addons/resource/models/resource_calendar_attendance.py
+++ b/addons/resource/models/resource_calendar_attendance.py
@@ -70,7 +70,7 @@ class ResourceCalendarAttendance(models.Model):
section_names = {'0': _('First week'), '1': _('Second week')}
section_info = {True: _('this week'), False: _('other week')}
for record in self.filtered(lambda l: l.display_type == 'line_section'):
- section_name = "%s (%s)" % (section_names[record.week_type], section_info[this_week_type == record.week_type])
+ section_name = f"{section_names[record.week_type]} ({section_info[this_week_type == record.week_type]})"
record.display_name = section_name
def _copy_attendance_vals(self):
diff --git a/addons/sale/models/sale_order.py b/addons/sale/models/sale_order.py
index 72803e6cfee..51aead66ee6 100644
--- a/addons/sale/models/sale_order.py
+++ b/addons/sale/models/sale_order.py
@@ -295,6 +295,18 @@ class SaleOrder(models.Model):
#=== COMPUTE METHODS ===#
+
+
+ @api.depends_context('sale_show_partner_name')
+ def _compute_display_name(self):
+ if not self._context.get('sale_show_partner_name'):
+ return super()._compute_display_name()
+ for order in self:
+ name = order.name
+ if order.partner_id.name:
+ name = f'{name} - {order.partner_id.name}'
+ order.display_name = name
+
@api.depends('company_id')
def _compute_require_signature(self):
for order in self:
@@ -1557,17 +1569,6 @@ class SaleOrder(models.Model):
upselling_orders = filtered_self.filtered(lambda so: so.invoice_status == 'upselling')
upselling_orders._create_upsell_activity()
- def name_get(self):
- if self._context.get('sale_show_partner_name'):
- res = []
- for order in self:
- name = order.name
- if order.partner_id.name:
- name = f'{name} - {order.partner_id.name}'
- res.append((order.id, name))
- return res
- return super().name_get()
-
#=== BUSINESS METHODS ===#
def _create_upsell_activity(self):
diff --git a/addons/sale/models/sale_order_line.py b/addons/sale/models/sale_order_line.py
index 2132330a960..0d0a9db29b4 100644
--- a/addons/sale/models/sale_order_line.py
+++ b/addons/sale/models/sale_order_line.py
@@ -263,6 +263,15 @@ class SaleOrderLine(models.Model):
#=== COMPUTE METHODS ===#
+ def _compute_display_name(self):
+ name_per_id = self._additional_name_per_id()
+ for so_line in self.sudo():
+ name = '{} - {}'.format(so_line.order_id.name, so_line.name and so_line.name.split('\n')[0] or so_line.product_id.name)
+ additional_name = name_per_id.get(so_line.id)
+ if additional_name:
+ name = f'{name} {additional_name}'
+ so_line.display_name = name
+
@api.depends('product_id')
def _compute_product_template_id(self):
for line in self:
@@ -1157,17 +1166,6 @@ class SaleOrderLine(models.Model):
if so_line.order_partner_id.ref or so_line.order_partner_id.name
}
- def name_get(self):
- result = []
- name_per_id = self._additional_name_per_id()
- for so_line in self.sudo():
- name = '%s - %s' % (so_line.order_id.name, so_line.name and so_line.name.split('\n')[0] or so_line.product_id.name)
- additional_name = name_per_id.get(so_line.id)
- if additional_name:
- name = '%s %s' % (name, additional_name)
- result.append((so_line.id, name))
- return result
-
#=== HOOKS ===#
def _is_delivery(self):
diff --git a/addons/sale/tests/test_sale_order.py b/addons/sale/tests/test_sale_order.py
index 8fd2591eecb..dceb246abb1 100644
--- a/addons/sale/tests/test_sale_order.py
+++ b/addons/sale/tests/test_sale_order.py
@@ -290,7 +290,7 @@ class TestSaleOrder(SaleCommon):
"No validity date must be specified if the company validity duration is 0")
def test_so_names(self):
- """Test custom context key for name_get & name_search.
+ """Test custom context key for display_name & name_search.
Note: this key is used in sale_expense & sale_timesheet modules.
"""
@@ -302,7 +302,7 @@ class TestSaleOrder(SaleCommon):
self.assertNotIn(self.sale_order.partner_id.name, self.sale_order.display_name)
self.assertIn(
self.sale_order.partner_id.name,
- self.sale_order.with_context(sale_show_partner_name=True).name_get()[0][1])
+ self.sale_order.with_context(sale_show_partner_name=True).display_name)
def test_state_changes(self):
"""Test some untested state changes methods & logic."""
diff --git a/addons/sale_expense/models/sale_order.py b/addons/sale_expense/models/sale_order.py
index a8b34056416..258ff1349a5 100644
--- a/addons/sale_expense/models/sale_order.py
+++ b/addons/sale_expense/models/sale_order.py
@@ -13,7 +13,7 @@ class SaleOrder(models.Model):
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
- """ For expense, we want to show all sales order but only their name_get (no ir.rule applied), this is the only way to do it. """
+ """ For expense, we want to show all sales order but only their display_name (no ir.rule applied), this is the only way to do it. """
if (
self._context.get('sale_expense_all_order')
and self.user_has_groups('sales_team.group_sale_salesman')
diff --git a/addons/sale_expense/security/sale_expense_security.xml b/addons/sale_expense/security/sale_expense_security.xml
index 48edc9cf1db..e9080467417 100644
--- a/addons/sale_expense/security/sale_expense_security.xml
+++ b/addons/sale_expense/security/sale_expense_security.xml
@@ -1,7 +1,7 @@
-
+
Expense Employee can read confirmed SO
diff --git a/addons/sale_timesheet/models/project_update.py b/addons/sale_timesheet/models/project_update.py
index f1aa7b212fc..53a2ee57b12 100644
--- a/addons/sale_timesheet/models/project_update.py
+++ b/addons/sale_timesheet/models/project_update.py
@@ -37,7 +37,6 @@ class ProjectUpdate(models.Model):
('is_downpayment', '=', False),
]),
)
- name_by_sol = dict(sols.with_context(with_price_unit=True).name_get())
product_uom_unit = self.env.ref('uom.product_uom_unit')
product_uom_hour = self.env.ref('uom.product_uom_hour')
company_uom = self.env.company.timesheet_encode_uom_id
@@ -50,7 +49,7 @@ class ProjectUpdate(models.Model):
qty_invoiced = sol.product_uom._compute_quantity(sol.qty_invoiced, company_uom, raise_if_failure=False)
unit = sol.product_uom if is_unit else company_uom
services.append({
- 'name': name_by_sol[sol.id],
+ 'name': sol.with_context(with_price_unit=True).display_name,
'sold_value': product_uom_qty,
'effective_value': qty_delivered,
'remaining_value': product_uom_qty - qty_delivered,
diff --git a/addons/sale_timesheet/models/sale_order.py b/addons/sale_timesheet/models/sale_order.py
index 9cd71b24b3b..f03f64ead6a 100644
--- a/addons/sale_timesheet/models/sale_order.py
+++ b/addons/sale_timesheet/models/sale_order.py
@@ -157,12 +157,10 @@ class SaleOrderLine(models.Model):
has_displayed_warning_upsell = fields.Boolean('Has Displayed Warning Upsell')
timesheet_ids = fields.One2many('account.analytic.line', 'so_line', 'Timesheets')
- def name_get(self):
- res = super(SaleOrderLine, self).name_get()
+ def _compute_display_name(self):
+ super()._compute_display_name()
with_remaining_hours = self.env.context.get('with_remaining_hours')
if with_remaining_hours and any(line.remaining_hours_available for line in self):
- names = dict(res)
- result = []
company = self.env.company
encoding_uom = company.timesheet_encode_uom_id
is_hour = is_day = False
@@ -174,7 +172,6 @@ class SaleOrderLine(models.Model):
is_day = True
unit_label = _('days remaining')
for line in self:
- name = names.get(line.id)
if line.remaining_hours_available:
remaining_time = ''
if is_hour:
@@ -198,12 +195,10 @@ class SaleOrderLine(models.Model):
unit=unit_label
)
name = '{name}{remaining_time}'.format(
- name=name,
+ name=line.display_name,
remaining_time=remaining_time
)
- result.append((line.id, name))
- return result
- return res
+ line.display_name = name
@api.depends('product_id.service_policy')
def _compute_remaining_hours_available(self):
diff --git a/addons/snailmail/models/snailmail_letter.py b/addons/snailmail/models/snailmail_letter.py
index 42c48ddcc28..22c569d8819 100644
--- a/addons/snailmail/models/snailmail_letter.py
+++ b/addons/snailmail/models/snailmail_letter.py
@@ -60,7 +60,6 @@ class SnailmailLetter(models.Model):
"If not, it will got in state 'Error' and the error message will be displayed in the field 'Error Message'.")
error_code = fields.Selection([(err_code, err_code) for err_code in ERROR_CODES], string="Error")
info_msg = fields.Char('Information')
- display_name = fields.Char('Display Name', compute="_compute_display_name")
reference = fields.Char(string='Related Record', compute='_compute_reference', readonly=True, store=False)
@@ -78,7 +77,7 @@ class SnailmailLetter(models.Model):
def _compute_display_name(self):
for letter in self:
if letter.attachment_id:
- letter.display_name = "%s - %s" % (letter.attachment_id.name, letter.partner_id.name)
+ letter.display_name = f"{letter.attachment_id.name} - {letter.partner_id.name}"
else:
letter.display_name = letter.partner_id.name
@@ -237,7 +236,7 @@ class SnailmailLetter(models.Model):
'letter_id': letter.id,
'res_model': letter.model,
'res_id': letter.res_id,
- 'contact_address': letter.partner_id.with_context(snailmail_layout=True, show_address=True).name_get()[0][1],
+ 'contact_address': letter.partner_id.with_context(snailmail_layout=True, show_address=True).display_name,
'address': {
'name': recipient_name,
'street': letter.partner_id.street,
@@ -459,7 +458,7 @@ class SnailmailLetter(models.Model):
return all(record[key] for key in required_keys)
def _append_cover_page(self, invoice_bin: bytes):
- address_split = self.partner_id.with_context(show_address=True, lang='en_US')._get_name().split('\n')
+ address_split = self.partner_id.with_context(show_address=True, lang='en_US').display_name.split('\n')
address_split[0] = self.partner_id.name or self.partner_id.parent_id and self.partner_id.parent_id.name or address_split[0]
address = '
'.join(address_split)
address_x = 118 * mm
diff --git a/addons/spreadsheet/static/src/data_sources/metadata_repository.js b/addons/spreadsheet/static/src/data_sources/metadata_repository.js
index e8cf870951c..f90500ba873 100644
--- a/addons/spreadsheet/static/src/data_sources/metadata_repository.js
+++ b/addons/spreadsheet/static/src/data_sources/metadata_repository.js
@@ -31,7 +31,7 @@ import { EventBus } from "@odoo/owl";
*
* Implementation note:
* For the labels, when someone is asking for a display name which is not loaded yet,
- * the proxy returns directly (undefined) and a request for a name_get will
+ * the proxy returns directly (undefined) and a request to read display_name will
* be triggered. All the requests created are batched and send, with only one
* request per model, after a clock cycle.
* At the end of this process, an event is triggered (labels-fetched)
@@ -102,7 +102,7 @@ export class MetadataRepository extends EventBus {
}
/**
- * Save the result of a name_get request in the cache
+ * Save the result of display_name read request in the cache
*/
setDisplayName(model, id, result) {
this.displayNameRepository.setDisplayName(model, id, result);
diff --git a/addons/spreadsheet/static/src/global_filters/plugins/global_filters_ui_plugin.js b/addons/spreadsheet/static/src/global_filters/plugins/global_filters_ui_plugin.js
index d5129286080..7e0a39dc3d4 100644
--- a/addons/spreadsheet/static/src/global_filters/plugins/global_filters_ui_plugin.js
+++ b/addons/spreadsheet/static/src/global_filters/plugins/global_filters_ui_plugin.js
@@ -237,8 +237,8 @@ export default class GlobalFiltersUIPlugin extends spreadsheet.UIPlugin {
return "";
}
if (!this.recordsDisplayName[filter.id]) {
- this.orm.call(filter.modelName, "name_get", [value]).then((result) => {
- const names = result.map(([, name]) => name);
+ this.orm.call(filter.modelName, "read", [value, ["display_name"]]).then((result) => {
+ const names = result.map(({display_name}) => display_name);
this.recordsDisplayName[filter.id] = names;
this.dispatch("EVALUATE_CELLS", {
sheetId: this.getters.getActiveSheetId(),
diff --git a/addons/spreadsheet/static/src/pivot/pivot_model.js b/addons/spreadsheet/static/src/pivot/pivot_model.js
index cec6a1ebac3..75c89f29204 100644
--- a/addons/spreadsheet/static/src/pivot/pivot_model.js
+++ b/addons/spreadsheet/static/src/pivot/pivot_model.js
@@ -117,7 +117,7 @@ export function parsePivotFormulaFieldValue(field, groupValue) {
/**
* This class is an extension of PivotModel with some additional information
- * that we need in spreadsheet (name_get, isUsedInSheet, ...)
+ * that we need in spreadsheet (display_name, isUsedInSheet, ...)
*/
export class SpreadsheetPivotModel extends PivotModel {
/**
diff --git a/addons/spreadsheet/static/tests/global_filters/global_filters_model_test.js b/addons/spreadsheet/static/tests/global_filters/global_filters_model_test.js
index ef4ff9d2b73..8a54f1b07ae 100644
--- a/addons/spreadsheet/static/tests/global_filters/global_filters_model_test.js
+++ b/addons/spreadsheet/static/tests/global_filters/global_filters_model_test.js
@@ -637,14 +637,14 @@ QUnit.module("spreadsheet > Global filters model", {}, () => {
assert.expect(6);
const model = await createModelWithDataSource({
mockRPC: function (route, { method, args }) {
- if (method === "name_get") {
- const [resId] = args[0];
+ if (method === "read") {
+ const resId = args[0][0];
const names = {
1: "Jean-Jacques",
2: "Raoul Grosbedon",
};
- assert.step(`name_get_${resId}`);
- return [[resId, names[resId]]];
+ assert.step(`read_${resId}`);
+ return [{id: resId, display_name: names[resId]}]
}
},
});
@@ -685,7 +685,7 @@ QUnit.module("spreadsheet > Global filters model", {}, () => {
});
await nextTick();
assert.equal(getCellValue(model, "A10"), "Raoul Grosbedon");
- assert.verifySteps(["name_get_1", "name_get_2"]);
+ assert.verifySteps(["read_1", "read_2"]);
});
QUnit.test(
diff --git a/addons/spreadsheet/static/tests/lists/list_plugin_test.js b/addons/spreadsheet/static/tests/lists/list_plugin_test.js
index c1afd79160f..4e5c22140fe 100644
--- a/addons/spreadsheet/static/tests/lists/list_plugin_test.js
+++ b/addons/spreadsheet/static/tests/lists/list_plugin_test.js
@@ -46,7 +46,7 @@ QUnit.module("spreadsheet > list plugin", {}, () => {
assert.strictEqual(getCellValue(model, "A2"), "Spreadsheet");
});
- QUnit.test("Return name_get of many2one field", async (assert) => {
+ QUnit.test("Return display_name of many2one field", async (assert) => {
const { model } = await createSpreadsheetWithList({ columns: ["product_id"] });
assert.strictEqual(getCellValue(model, "A2"), "xphone");
});
diff --git a/addons/spreadsheet/static/tests/pivots/model/pivot_plugin_test.js b/addons/spreadsheet/static/tests/pivots/model/pivot_plugin_test.js
index 4a816bf27b6..763eeaf6419 100644
--- a/addons/spreadsheet/static/tests/pivots/model/pivot_plugin_test.js
+++ b/addons/spreadsheet/static/tests/pivots/model/pivot_plugin_test.js
@@ -427,7 +427,7 @@ QUnit.module("spreadsheet > pivot plugin", {}, () => {
assert.step(`${model}/${method}`);
await dataPromise;
}
- if (model === "product" && method === "name_get") {
+ if (model === "product" && method === "read") {
assert.ok(false, "should not be called because data is put in cache");
}
return result;
diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py
index 7fab3b6c7f3..5a95a647308 100644
--- a/addons/stock/models/stock_move.py
+++ b/addons/stock/models/stock_move.py
@@ -641,14 +641,12 @@ Please change the quantity done or the rounding precision of your unit of measur
defaults['additional'] = True # to trigger `_autoconfirm_picking`
return defaults
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for move in self:
- res.append((move.id, '%s%s%s>%s' % (
+ move.display_name = '%s%s%s>%s' % (
move.picking_id.origin and '%s/' % move.picking_id.origin or '',
move.product_id.code and '%s: ' % move.product_id.code or '',
- move.location_id.name, move.location_dest_id.name)))
- return res
+ move.location_id.name, move.location_dest_id.name)
@api.model_create_multi
def create(self, vals_list):
diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py
index ecc74970a3a..76691b2ecea 100644
--- a/addons/stock/models/stock_picking.py
+++ b/addons/stock/models/stock_picking.py
@@ -164,20 +164,17 @@ class PickingType(models.Model):
for record in self:
record[field_name] = count.get(record.id, 0)
- def name_get(self):
+ def _compute_display_name(self):
""" Display 'Warehouse_name: PickingType_name' """
- res = []
for picking_type in self:
if picking_type.warehouse_id:
- name = picking_type.warehouse_id.name + ': ' + picking_type.name
+ picking_type.display_name = f"{picking_type.warehouse_id.name}: {picking_type.name}"
else:
- name = picking_type.name
- res.append((picking_type.id, name))
- return res
+ picking_type.display_name = picking_type.name
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
- # Try to reverse the `name_get` structure
+ # Try to reverse the `display_name` structure
parts = name.split(': ')
if len(parts) == 2:
name_domain = [('warehouse_id.name', operator, parts[0]), ('name', operator, parts[1])]
diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py
index 785777dfc8c..4f164aa5d3d 100644
--- a/addons/stock/models/stock_quant.py
+++ b/addons/stock/models/stock_quant.py
@@ -543,9 +543,8 @@ class StockQuant(models.Model):
'target': 'new',
}
- def name_get(self):
+ def _compute_display_name(self):
"""name that will be displayed in the detailed operation"""
- name_parts = []
for record in self:
name = []
if self.env.user.has_group('stock.group_stock_multi_locations'):
@@ -556,10 +555,7 @@ class StockQuant(models.Model):
name.append(record.package_id.name)
if self.env.user.has_group('stock.group_tracking_owner') and record.owner_id:
name.append(record.owner_id.name)
- name_parts.append(name)
- if name_parts:
- return [(quant.id, ' - '.join(name)) if name else (quant.id, "- no data -") for quant, name in zip(self, name_parts)]
- return []
+ self.display_name = ' - '.join(name) if name else "- no data -"
@api.constrains('product_id')
def check_product_id(self):
diff --git a/addons/stock/tests/test_move_lines.py b/addons/stock/tests/test_move_lines.py
index 7a618ed872b..8f3581946cc 100644
--- a/addons/stock/tests/test_move_lines.py
+++ b/addons/stock/tests/test_move_lines.py
@@ -47,8 +47,8 @@ class StockMoveLine(TestStockCommon):
})
def test_pick_from_1(self):
- """ test quant name_get """
- self.assertEqual(self.quant.name_get()[0][1], 'WH/Stock/Shelf 1 - Lot 1 - Pack A - The Owner')
+ """ test quant display_name """
+ self.assertEqual(self.quant.display_name, 'WH/Stock/Shelf 1 - Lot 1 - Pack A - The Owner')
def test_pick_from_2(self):
""" Create a move line from a quant"""
diff --git a/addons/stock/wizard/stock_track_confirmation.py b/addons/stock/wizard/stock_track_confirmation.py
index cd93c999781..27ea52adcac 100644
--- a/addons/stock/wizard/stock_track_confirmation.py
+++ b/addons/stock/wizard/stock_track_confirmation.py
@@ -25,12 +25,12 @@ class StockTrackingLines(models.TransientModel):
_name = 'stock.track.line'
_description = 'Stock Track Line'
- product_display_name = fields.Char('Name', compute='_compute_display_name', readonly=True)
+ product_display_name = fields.Char('Name', compute='_compute_product_display_name', readonly=True)
product_id = fields.Many2one('product.product', 'Product', readonly=True)
tracking = fields.Selection(related='product_id.tracking')
wizard_id = fields.Many2one('stock.track.confirmation', readonly=True)
- def _compute_display_name(self):
+ def _compute_product_display_name(self):
""" Onchange results in product.display_name not being directly accessible """
for line in self:
line.product_display_name = line.product_id._origin.display_name
diff --git a/addons/survey/models/survey_user_input.py b/addons/survey/models/survey_user_input.py
index 2c1313e9d3b..f38ecdf0701 100644
--- a/addons/survey/models/survey_user_input.py
+++ b/addons/survey/models/survey_user_input.py
@@ -671,9 +671,7 @@ class SurveyUserInputLine(models.Model):
line.display_name = fields.Datetime.to_string(line.value_datetime)
elif line.answer_type == 'suggestion':
if line.matrix_row_id:
- line.display_name = '%s: %s' % (
- line.suggested_answer_id.value,
- line.matrix_row_id.value)
+ line.display_name = f'{line.suggested_answer_id.value}: {line.matrix_row_id.value}'
else:
line.display_name = line.suggested_answer_id.value
diff --git a/addons/test_base_import/tests/test_base_import.py b/addons/test_base_import/tests/test_base_import.py
index c7b0ac0ef10..de585651e88 100644
--- a/addons/test_base_import/tests/test_base_import.py
+++ b/addons/test_base_import/tests/test_base_import.py
@@ -86,7 +86,7 @@ class TestBasicFields(BaseImportCase):
self.assertEqualFields(self.get_fields('char.stillreadonly'), [ID_FIELD])
def test_m2o(self):
- """ M2O fields should allow import of themselves (name_get),
+ """ M2O fields should allow import of themselves (display_name),
their id and their xid"""
self.assertEqualFields(self.get_fields('m2o'), make_field(
field_type='many2one', comodel_name=base_import_model('m2o.related'), model_name=base_import_model('m2o'),
diff --git a/addons/test_xlsx_export/models.py b/addons/test_xlsx_export/models.py
index 6e4d6d9fa0a..885fcea9631 100644
--- a/addons/test_xlsx_export/models.py
+++ b/addons/test_xlsx_export/models.py
@@ -9,8 +9,9 @@ class NewModel(models.Model):
value = fields.Integer(default=4)
- def name_get(self):
- return [(record.id, "%s:%s" % (self._name, record.value)) for record in self]
+ def _compute_display_name(self):
+ for record in self:
+ record.display_name = f"{self._name}:{record.value}"
class GroupOperator(models.Model):
_name = 'export.group_operator'
diff --git a/addons/uom/models/uom_uom.py b/addons/uom/models/uom_uom.py
index 7d84ae13d33..bf9796579aa 100644
--- a/addons/uom/models/uom_uom.py
+++ b/addons/uom/models/uom_uom.py
@@ -195,7 +195,7 @@ class UoM(models.Model):
else:
values['category_id'] = EnglishUoMCateg.name_create('Unsorted/Imported Units')[0]
new_uom = self.create(values)
- return new_uom.name_get()[0]
+ return new_uom.id, new_uom.display_name
def _compute_quantity(self, qty, to_unit, round=True, rounding_method='UP', raise_if_failure=True):
""" Convert the given quantity from the current UoM `self` into a given one
diff --git a/addons/web/static/src/core/orm_service.js b/addons/web/static/src/core/orm_service.js
index abb5365c841..0c656b5d0fa 100644
--- a/addons/web/static/src/core/orm_service.js
+++ b/addons/web/static/src/core/orm_service.js
@@ -147,7 +147,9 @@ export class ORM {
if (!ids.length) {
return Promise.resolve([]);
}
- return this.call(model, "name_get", [ids], kwargs);
+ return this.call(model, "read", [ids, ["display_name"]], kwargs).then(
+ (data) => data && data.map(({id, display_name}) => [id, display_name])
+ );
}
/**
diff --git a/addons/web/static/src/legacy/js/views/basic/basic_model.js b/addons/web/static/src/legacy/js/views/basic/basic_model.js
index a67f7dc7b0d..803d7591bf6 100644
--- a/addons/web/static/src/legacy/js/views/basic/basic_model.js
+++ b/addons/web/static/src/legacy/js/views/basic/basic_model.js
@@ -1603,7 +1603,7 @@ var BasicModel = AbstractModel.extend({
* Apply an x2one (either a many2one or a reference field) change. There is
* a need for this function because the server only gives an id when a
* onchange modifies a many2one field. For this reason, we need (sometimes)
- * to do a /name_get to fetch a display_name.
+ * to do a read of display_name.
*
* Moreover, for the many2one case, a new value can sometimes be set (i.e.
* a display_name is given, but no id). When this happens, we first do a
@@ -1673,12 +1673,12 @@ var BasicModel = AbstractModel.extend({
// TODO: refactor this to use _fetchNameGet
def = this._rpc({
model: coModel,
- method: 'name_get',
- args: [data.id],
+ method: 'read',
+ args: [data.id, ['display_name']],
context: this._getContext(record, { fieldName, viewType }),
})
.then(function (result) {
- rel_data.display_name = result[0][1];
+ rel_data.display_name = result[0]['display_name'];
});
}
return Promise.resolve(def).then(function () {
@@ -2479,7 +2479,7 @@ var BasicModel = AbstractModel.extend({
}
},
/**
- * Fetch name_get for a record datapoint.
+ * Fetch display_name for a record datapoint.
*
* @param {Object} dataPoint
* @returns {Promise}
@@ -2487,15 +2487,15 @@ var BasicModel = AbstractModel.extend({
_fetchNameGet: function (dataPoint) {
return this._rpc({
model: dataPoint.model,
- method: 'name_get',
- args: [dataPoint.res_id],
+ method: 'read',
+ args: [dataPoint.res_id, ['display_name']],
context: dataPoint.getContext(),
}).then(function (result) {
- dataPoint.data.display_name = result[0][1];
+ dataPoint.data.display_name = result[0]['display_name'];
});
},
/**
- * Fetch name_get for a field of type Many2one or Reference
+ * Fetch display_name for a field of type Many2one or Reference
*
* @private
* @params {Object} list: must be a datapoint of type list
@@ -2530,14 +2530,14 @@ var BasicModel = AbstractModel.extend({
}
return this._rpc({
model: model,
- method: 'name_get',
- args: [unique(ids)],
+ method: 'read',
+ args: [unique(ids), ['display_name']],
context: list.context,
})
- .then(function (name_gets) {
+ .then(function (readRecords) {
records.forEach((record) => {
- var nameGet = name_gets.find(nameGet => nameGet[0] === record.data.id);
- record.data.display_name = nameGet[1];
+ const readRecord = readRecords.find(readRecord => readRecord['id'] === record.data.id);
+ record.data.display_name = readRecord['display_name'];
});
});
},
@@ -2585,7 +2585,7 @@ var BasicModel = AbstractModel.extend({
});
},
/**
- * Fetch the `name_get` for a reference field.
+ * Fetch the `display_name` for a reference field.
*
* @private
* @param {Object} record
@@ -2601,15 +2601,12 @@ var BasicModel = AbstractModel.extend({
if (model && model !== 'False' && resID) {
def = self._rpc({
model: model,
- method: 'name_get',
- args: [resID],
+ method: 'read',
+ args: [resID, ['display_name']],
context: record.getContext({fieldName: fieldName}),
}).then(function (result) {
return self._makeDataPoint({
- data: {
- id: result[0][0],
- display_name: result[0][1],
- },
+ data: result[0],
modelName: model,
parentID: record.id,
});
@@ -2635,19 +2632,16 @@ var BasicModel = AbstractModel.extend({
var parent = datapoints[ids[0]][0];
var def = self._rpc({
model: model,
- method: 'name_get',
- args: [ids],
+ method: 'read',
+ args: [ids, ['display_name']],
context: self.localData[parent].getContext({fieldName: fieldName, withoutRecordData: true}),
}).then(function (result) {
result.forEach((el) => {
- var parentIDs = datapoints[el[0]];
+ var parentIDs = datapoints[el['id']];
parentIDs.forEach((parentID) => {
var parent = self.localData[parentID];
var referenceDp = self._makeDataPoint({
- data: {
- id: el[0],
- display_name: el[1],
- },
+ data: el,
modelName: model,
parentID: parent.id,
});
@@ -2658,7 +2652,7 @@ var BasicModel = AbstractModel.extend({
return def;
},
/**
- * Fetch the extra data (`name_get`) for the reference fields of the record
+ * Fetch the extra data (`display_name`) for the reference fields of the record
* model.
*
* @private
@@ -2698,7 +2692,7 @@ var BasicModel = AbstractModel.extend({
var toFetch = this._getDataToFetchByModel(list, fieldName);
var defs = [];
- // one name_get by model
+ // one display_name read by model
Object.entries(toFetch).forEach(([model, datapoints]) => {
defs.push(self._fetchReferenceData(datapoints, model, fieldName));
});
@@ -2741,7 +2735,7 @@ var BasicModel = AbstractModel.extend({
});
var defs = [];
- // one name_get by model
+ // one display_name read by model
Object.entries(toFetch).forEach(([model, datapoints]) => {
defs.push(self._fetchReferenceData(datapoints, model, fieldName));
});
@@ -2750,7 +2744,7 @@ var BasicModel = AbstractModel.extend({
},
/**
* Batch requests for all reference field in list's children.
- * Called by _readGroup to make only one 'name_get' rpc by fieldName.
+ * Called by _readGroup to make only one display_name 'read' rpc by fieldName.
*
* @param {Object} list a valid resource object
* @returns {Promise}
@@ -2939,7 +2933,7 @@ var BasicModel = AbstractModel.extend({
});
},
/**
- * Fetches the `name_get` associated to the reference widget if the field is
+ * Fetches the `display_name` associated to the reference widget if the field is
* a `char` (which is a supported case).
*
* @private
@@ -2951,7 +2945,7 @@ var BasicModel = AbstractModel.extend({
_fetchSpecialReference: function (record, fieldName, fieldInfo) {
var field = record.fields[fieldName];
if (field.type === 'char') {
- // if the widget reference is set on a char field, the name_get
+ // if the widget reference is set on a char field, the display_name
// needs to be fetched a posteriori
return Promise.resolve(this._fetchReference(record, fieldName));
} else if (fieldInfo.options.model_field) {
@@ -4504,17 +4498,17 @@ var BasicModel = AbstractModel.extend({
const _changes = record._changes || {};
const relRecordId = _changes[name] || record.data[name];
if (!relRecordId) {
- return; // field is unset, no need to do the name_get
+ return; // field is unset, no need to do the display_name read
}
var relRecord = self.localData[relRecordId];
defs.push(self._rpc({
model: field.relation,
- method: 'name_get',
- args: [relRecord.data.id],
+ method: 'read',
+ args: [relRecord.data.id, ['display_name']],
context: self._getContext(record, {fieldName: name, viewType: viewType, withoutRecordData: true}),
})
.then(function (result) {
- relRecord.data.display_name = result[0][1];
+ relRecord.data.display_name = result[0]['display_name'];
}));
}
}
diff --git a/addons/web/static/src/search/search_arch_parser.js b/addons/web/static/src/search/search_arch_parser.js
index 61911f02a0d..534cf945afe 100644
--- a/addons/web/static/src/search/search_arch_parser.js
+++ b/addons/web/static/src/search/search_arch_parser.js
@@ -160,9 +160,9 @@ export class SearchArchParser extends XMLParser {
} else if (fieldType === "many2one") {
this.labels.push((orm) => {
return orm
- .call(relation, "name_get", [value], { context })
+ .call(relation, "read", [value, ['display_name']], { context })
.then((results) => {
- preField.defaultAutocompleteValue.label = results[0][1];
+ preField.defaultAutocompleteValue.label = results[0]['display_name'];
});
});
}
diff --git a/addons/web/static/src/views/fields/properties/property_value.js b/addons/web/static/src/views/fields/properties/property_value.js
index a15b6ba2fad..603cfae3947 100644
--- a/addons/web/static/src/views/fields/properties/property_value.js
+++ b/addons/web/static/src/views/fields/properties/property_value.js
@@ -328,7 +328,7 @@ export class PropertyValue extends Component {
* @returns {array} [record id, record name]
*/
async _nameGet(recordId) {
- const result = await this.orm.call(this.props.comodel, "name_get", [[recordId]], {
+ const result = await this.orm.nameGet(this.props.comodel, [recordId], {
context: this.props.context,
});
return result[0];
diff --git a/addons/web/static/src/views/fields/radio/radio_field.js b/addons/web/static/src/views/fields/radio/radio_field.js
index 79383b199fc..aa4acb2b2df 100644
--- a/addons/web/static/src/views/fields/radio/radio_field.js
+++ b/addons/web/static/src/views/fields/radio/radio_field.js
@@ -91,7 +91,7 @@ registry.category("fields").add("radio", radioField);
export async function preloadRadio(orm, record, fieldName, { domain }) {
const field = record.fields[fieldName];
const records = await orm.searchRead(field.relation, domain, ["id"]);
- return await orm.call(field.relation, "name_get", [records.map((record) => record.id)]);
+ return await orm.nameGet(field.relation, [records.map((record) => record.id)]);
}
registry.category("preloadedData").add("radio", {
diff --git a/addons/web/static/src/views/relational_model.js b/addons/web/static/src/views/relational_model.js
index 4bdfbc4c224..31e5ba6886a 100644
--- a/addons/web/static/src/views/relational_model.js
+++ b/addons/web/static/src/views/relational_model.js
@@ -146,9 +146,9 @@ class RequestBatcherORM extends ORM {
}
/**
- * Entry point to batch "name_get" calls. If the `resModel` argument has
+ * Entry point to batch display_name "read" calls. If the `resModel` argument has
* already been called, the given ids are added to the previous list of ids
- * to perform a single name_get call.
+ * to perform a single read of display_name call.
*
* @param {string} resModel
* @param {number[]} resIds
diff --git a/addons/web/static/src/views/sample_server.js b/addons/web/static/src/views/sample_server.js
index 7ea837ff08a..847bc37bc64 100644
--- a/addons/web/static/src/views/sample_server.js
+++ b/addons/web/static/src/views/sample_server.js
@@ -370,6 +370,7 @@ export class SampleServer {
* @returns {Array[]} a list of [id, display_name]
*/
_mockNameGet(params) {
+ throw new Error("name_get is deprecated, it shouldn't be called");
const { model, args } = params;
let ids = args[0];
if (!args.length) {
diff --git a/addons/web/static/tests/core/orm_service_tests.js b/addons/web/static/tests/core/orm_service_tests.js
index fbd481c76c0..9de164cfa6d 100644
--- a/addons/web/static/tests/core/orm_service_tests.js
+++ b/addons/web/static/tests/core/orm_service_tests.js
@@ -152,9 +152,9 @@ QUnit.test("nameGet method", async (assert) => {
const env = await makeTestEnv();
const context = { complete: true };
await env.services.orm.nameGet("sale.order", [2, 5], { context });
- assert.strictEqual(query.route, "/web/dataset/call_kw/sale.order/name_get");
+ assert.strictEqual(query.route, "/web/dataset/call_kw/sale.order/read");
assert.deepEqual(query.params, {
- args: [[2, 5]],
+ args: [[2, 5], ['display_name']],
kwargs: {
context: {
complete: true,
@@ -163,7 +163,7 @@ QUnit.test("nameGet method", async (assert) => {
uid: 7,
},
},
- method: "name_get",
+ method: "read",
model: "sale.order",
});
});
diff --git a/addons/web/static/tests/helpers/mock_server.js b/addons/web/static/tests/helpers/mock_server.js
index 2b59cb3aa9a..53cd22c3031 100644
--- a/addons/web/static/tests/helpers/mock_server.js
+++ b/addons/web/static/tests/helpers/mock_server.js
@@ -590,7 +590,7 @@ export class MockServer {
/**
* Converts an Object representing a record to actual return Object of the
* python `onchange` method.
- * Specifically, it applies `name_get` on many2one's and transforms raw id
+ * Specifically, it reads `display_name` on many2one's and transforms raw id
* list in orm command lists for x2many's.
* For x2m fields that add or update records (ORM commands 0 and 1), it is
* recursive.
@@ -603,7 +603,6 @@ export class MockServer {
Object.entries(values).forEach(([fname, val]) => {
const field = this.models[modelName].fields[fname];
if (field.type === "many2one" && typeof val === "number") {
- // implicit name_get
const m2oRecord = this.models[field.relation].records.find((r) => r.id === val);
values[fname] = [val, m2oRecord.display_name];
} else if (field.type === "one2many" || field.type === "many2many") {
@@ -671,8 +670,6 @@ export class MockServer {
return this.mockGetViews(args.model, args.kwargs);
case "name_create":
return this.mockNameCreate(args.model, args.args[0], args.kwargs);
- case "name_get":
- return this.mockNameGet(args.model, args.args);
case "name_search":
return this.mockNameSearch(args.model, args.args, args.kwargs);
case "onchange":
@@ -874,30 +871,6 @@ export class MockServer {
return [id, name];
}
- /**
- * Simulate a 'name_get' operation
- *
- * @private
- * @param {string} model
- * @param {Array} args
- * @returns {Array[]} a list of [id, display_name]
- */
- mockNameGet(model, args) {
- var ids = args[0];
- if (!args.length) {
- throw new Error("name_get: expected one argument");
- } else if (!ids) {
- return [];
- }
- if (!Array.isArray(ids)) {
- ids = [ids];
- }
- var records = this.models[model].records;
- var names = ids.map((id) =>
- id ? [id, records.find((r) => r.id === id).display_name] : [null, ""]
- );
- return names;
- }
/**
* Simulate a 'name_search' operation.
diff --git a/addons/web/static/tests/legacy/helpers/mock_server.js b/addons/web/static/tests/legacy/helpers/mock_server.js
index c8ab53fc903..93fb6ce52d4 100644
--- a/addons/web/static/tests/legacy/helpers/mock_server.js
+++ b/addons/web/static/tests/legacy/helpers/mock_server.js
@@ -229,7 +229,7 @@ var MockServer = Class.extend({
/**
* Converts an Object representing a record to actual return Object of the
* python `onchange` method.
- * Specifically, it applies `name_get` on many2one's and transforms raw id
+ * Specifically, it reads `display_name` on many2one's and transforms raw id
* list in orm command lists for x2many's.
* For x2m fields that add or update records (ORM commands 0 and 1), it is
* recursive.
@@ -243,7 +243,6 @@ var MockServer = Class.extend({
Object.entries(values).forEach(([fname, val]) => {
const field = this.data[model].fields[fname];
if (field.type === 'many2one' && typeof val === 'number') {
- // implicit name_get
const m2oRecord = this.data[field.relation].records.find(r => r.id === val);
values[fname] = [val, m2oRecord.display_name];
} else if (field.type === 'one2many' || field.type === 'many2many') {
@@ -1234,31 +1233,6 @@ var MockServer = Class.extend({
});
return views;
},
- /**
- * Simulate a 'name_get' operation
- *
- * @private
- * @param {string} model
- * @param {Array} args
- * @returns {Array[]} a list of [id, display_name]
- */
- _mockNameGet: function (model, args) {
- var ids = args[0];
- if (!args.length) {
- throw new Error("name_get: expected one argument");
- }
- else if (!ids) {
- return []
- }
- if (!Array.isArray(ids)) {
- ids = [ids];
- }
- var records = this.data[model].records;
- var names = ids.map((id) => {
- return id ? [id, records.find((r) => r.id === id).display_name] : [null, ""];
- });
- return names;
- },
/**
* Simulate a 'name_create' operation
*
@@ -2029,8 +2003,6 @@ var MockServer = Class.extend({
case 'get_views':
return this._mockGetViews(args.model, args.kwargs);
- case 'name_get':
- return this._mockNameGet(args.model, args.args);
case 'name_create':
return this._mockNameCreate(args.model, args.args);
diff --git a/addons/web/static/tests/legacy/mockserver_tests.js b/addons/web/static/tests/legacy/mockserver_tests.js
index 9db8e827c2e..4f2a06be9ec 100644
--- a/addons/web/static/tests/legacy/mockserver_tests.js
+++ b/addons/web/static/tests/legacy/mockserver_tests.js
@@ -109,110 +109,6 @@ QUnit.module("Legacy MockServer", {
);
});
- QUnit.test("performRpc: name_get with no args", async function (assert) {
- assert.expect(2);
- const server = new MockServer(this.data, {});
- try {
- await server.performRpc("", {
- model: "res.partner",
- method: "name_get",
- args: [],
- kwargs: {},
- });
- } catch {
- assert.step("name_get failed")
- }
- assert.verifySteps(["name_get failed"])
- });
-
- QUnit.test("performRpc: name_get with undefined arg", async function (assert) {
- assert.expect(1);
- const server = new MockServer(this.data, {});
- const result = await server.performRpc("", {
- model: "res.partner",
- method: "name_get",
- args: [undefined],
- kwargs: {},
- });
- assert.deepEqual(result, [])
- });
-
- QUnit.test("performRpc: name_get with a single id", async function (assert) {
- assert.expect(1);
- const server = new MockServer(this.data, {});
- const result = await server.performRpc("", {
- model: "res.partner",
- method: "name_get",
- args: [1],
- kwargs: {},
- });
- assert.deepEqual(result, [[1, "Jean-Michel"]]);
- });
-
- QUnit.test("performRpc: name_get with array of ids", async function (assert) {
- assert.expect(1);
- const server = new MockServer(this.data, {});
- const result = await server.performRpc("", {
- model: "res.partner",
- method: "name_get",
- args: [[1]],
- kwargs: {},
- });
- assert.deepEqual(result, [[1, "Jean-Michel"]]);
- });
-
- QUnit.test("performRpc: name_get with invalid id", async function (assert) {
- assert.expect(2);
- const server = new MockServer(this.data, {});
- try {
- await server.performRpc("", {
- model: "res.partner",
- method: "name_get",
- args: [11111],
- kwargs: {},
- });
- } catch {
- assert.step("name_get failed")
- }
- assert.verifySteps(["name_get failed"])
- });
-
- QUnit.test("performRpc: name_get with id and undefined id", async function (assert) {
- assert.expect(1);
- const server = new MockServer(this.data, {});
- const result = await server.performRpc("", {
- model: "res.partner",
- method: "name_get",
- args: [[undefined, 1]],
- kwargs: {},
- });
- assert.deepEqual(result, [[null, ""], [1, "Jean-Michel"]]);
- });
-
- QUnit.test("performRpc: name_get with single id 0", async function (assert) {
- assert.expect(1);
- const server = new MockServer(this.data, {});
- const result = await server.performRpc("", {
- model: "res.partner",
- method: "name_get",
- args: [0],
- kwargs: {},
- });
- assert.deepEqual(result, []);
- });
-
- QUnit.test("performRpc: name_get with array of id 0", async function (assert) {
- assert.expect(1);
- const server = new MockServer(this.data, {});
- const result = await server.performRpc("", {
- model: "res.partner",
- method: "name_get",
- args: [[0]],
- kwargs: {},
- });
- assert.deepEqual(result, [[null, ""]]);
- });
-
QUnit.test("performRpc: search with active_test=false", async function (assert) {
assert.expect(1);
const server = new MockServer(this.data, {});
diff --git a/addons/web/static/tests/legacy/views/basic_model_tests.js b/addons/web/static/tests/legacy/views/basic_model_tests.js
index 11b5aed7571..bcd22b44ffe 100644
--- a/addons/web/static/tests/legacy/views/basic_model_tests.js
+++ b/addons/web/static/tests/legacy/views/basic_model_tests.js
@@ -368,7 +368,7 @@
Model: BasicModel,
data: this.data,
mockRPC: function (route, args) {
- if (args.method === 'name_get') {
+ if (args.method === 'read' && args.args[1].length === 1 && args.args[1][0] === 'display_name') {
assert.strictEqual(args.model, 'product');
}
return this._super(route, args);
@@ -448,7 +448,7 @@
Model: BasicModel,
data: this.data,
mockRPC: function (route, args) {
- if (args.method === 'name_get') {
+ if (args.method === 'read' && args.args[1].length === 1 && args.args[1][0] === 'display_name') {
assert.strictEqual(args.model, 'product');
}
return this._super(route, args);
@@ -2083,9 +2083,9 @@
data: this.data,
mockRPC: function (route, args) {
assert.step(route);
- if (route === "/web/dataset/call_kw/product/name_get") {
- assert.deepEqual(args.args, [[37, 41]],
- "the name_get should contain the product ids");
+ if (route === "/web/dataset/call_kw/product/read") {
+ assert.deepEqual(args.args, [[37, 41], ['display_name']],
+ "the read display_name should contain the product ids");
}
return this._super(route, args);
},
@@ -2095,9 +2095,9 @@
var record = model.get(resultID);
assert.strictEqual(record.data[0].data.reference.data.display_name, "xphone",
- "name_get should have been correctly fetched");
- assert.verifySteps(["/web/dataset/search_read", "/web/dataset/call_kw/product/name_get"],
- "should have done 2 rpc (searchread and name_get for product)");
+ "display_name should have been correctly fetched");
+ assert.verifySteps(["/web/dataset/search_read", "/web/dataset/call_kw/product/read"],
+ "should have done 2 rpc (searchread and read display_name for product)");
model.destroy();
});
diff --git a/addons/web/static/tests/mock_server_tests.js b/addons/web/static/tests/mock_server_tests.js
index 4d471c2ba27..d2e6d850668 100644
--- a/addons/web/static/tests/mock_server_tests.js
+++ b/addons/web/static/tests/mock_server_tests.js
@@ -195,105 +195,6 @@ QUnit.module("MockServer", (hooks) => {
assert.deepEqual(result, [{ id: 1, name: "Jean-Michel" }]);
});
- QUnit.test("performRPC: name_get with no args", async function (assert) {
- const server = new MockServer(data, {});
- try {
- await server.performRPC("", {
- model: "partner",
- method: "name_get",
- args: [],
- kwargs: {},
- });
- } catch {
- assert.step("name_get failed");
- }
- assert.verifySteps(["name_get failed"]);
- });
-
- QUnit.test("performRPC: name_get with undefined arg", async function (assert) {
- const server = new MockServer(data, {});
- const result = await server.performRPC("", {
- model: "partner",
- method: "name_get",
- args: [undefined],
- kwargs: {},
- });
- assert.deepEqual(result, []);
- });
-
- QUnit.test("performRPC: name_get with a single id", async function (assert) {
- const server = new MockServer(data, {});
- const result = await server.performRPC("", {
- model: "partner",
- method: "name_get",
- args: [1],
- kwargs: {},
- });
- assert.deepEqual(result, [[1, "Jean-Michel"]]);
- });
-
- QUnit.test("performRPC: name_get with array of ids", async function (assert) {
- const server = new MockServer(data, {});
- const result = await server.performRPC("", {
- model: "partner",
- method: "name_get",
- args: [[1]],
- kwargs: {},
- });
- assert.deepEqual(result, [[1, "Jean-Michel"]]);
- });
-
- QUnit.test("performRPC: name_get with invalid id", async function (assert) {
- const server = new MockServer(data, {});
- try {
- await server.performRPC("", {
- model: "partner",
- method: "name_get",
- args: [11111],
- kwargs: {},
- });
- } catch {
- assert.step("name_get failed");
- }
- assert.verifySteps(["name_get failed"]);
- });
-
- QUnit.test("performRPC: name_get with id and undefined id", async function (assert) {
- const server = new MockServer(data, {});
- const result = await server.performRPC("", {
- model: "partner",
- method: "name_get",
- args: [[undefined, 1]],
- kwargs: {},
- });
- assert.deepEqual(result, [
- [null, ""],
- [1, "Jean-Michel"],
- ]);
- });
-
- QUnit.test("performRPC: name_get with single id 0", async function (assert) {
- const server = new MockServer(data, {});
- const result = await server.performRPC("", {
- model: "partner",
- method: "name_get",
- args: [0],
- kwargs: {},
- });
- assert.deepEqual(result, []);
- });
-
- QUnit.test("performRPC: name_get with array of id 0", async function (assert) {
- const server = new MockServer(data, {});
- const result = await server.performRPC("", {
- model: "partner",
- method: "name_get",
- args: [[0]],
- kwargs: {},
- });
- assert.deepEqual(result, [[null, ""]]);
- });
-
QUnit.test("performRPC: search_count", async function (assert) {
const server = new MockServer(data, {});
const result = await server.performRPC("", {
diff --git a/addons/web/static/tests/search/search_bar_tests.js b/addons/web/static/tests/search/search_bar_tests.js
index 3433730b8d3..b6017fb7456 100644
--- a/addons/web/static/tests/search/search_bar_tests.js
+++ b/addons/web/static/tests/search/search_bar_tests.js
@@ -1020,7 +1020,7 @@ QUnit.module("Search", (hooks) => {
const def = makeDeferred();
const mockRPC = async (_, args) => {
- if (args.method === "name_get") {
+ if (args.method === "read") {
await def;
}
};
diff --git a/addons/web/static/tests/views/fields/many2one_field_tests.js b/addons/web/static/tests/views/fields/many2one_field_tests.js
index d05e4b6f4be..97a13280dd3 100644
--- a/addons/web/static/tests/views/fields/many2one_field_tests.js
+++ b/addons/web/static/tests/views/fields/many2one_field_tests.js
@@ -347,7 +347,7 @@ QUnit.module("Fields", (hooks) => {
`,
mockRPC(route, { method, kwargs }) {
- if (method === "name_get") {
+ if (method === "read") {
assert.strictEqual(
kwargs.context.blip,
undefined,
@@ -422,9 +422,9 @@ QUnit.module("Fields", (hooks) => {
`,
- mockRPC(route, { method, kwargs }) {
- if (method === "name_get" && kwargs.context.show_address) {
- return [[4, "aaa\nStreet\nCity ZIP"]];
+ mockRPC(route, { args, method, kwargs }) {
+ if (method === "read" && args[1].length === 1 && args[1][0] === "display_name" && kwargs.context.show_address) {
+ return [{id: 4, display_name: "aaa\nStreet\nCity ZIP"}];
}
},
});
@@ -462,8 +462,8 @@ QUnit.module("Fields", (hooks) => {
`,
mockRPC(route, { args, kwargs, method }) {
- if (method === "name_get" && kwargs.context.show_address) {
- return args.map((id) => [id, namegets[id]]);
+ if (method === "read" && args[1].length === 1 && args[1][0] === "display_name" && kwargs.context.show_address) {
+ return args.map((id) => ({id, display_name: namegets[id]}));
}
},
});
@@ -521,9 +521,9 @@ QUnit.module("Fields", (hooks) => {
`,
- mockRPC(route, { kwargs, method, model }) {
- if (method === "name_get" && kwargs.context.show_address) {
- return [[2, "second record\nrue morgue\nparis 75013"]];
+ mockRPC(route, { args, kwargs, method }) {
+ if (method === "read" && args[1].length === 1 && args[1][0] === "display_name" && kwargs.context.show_address) {
+ return [{id: 2, display_name: "second record\nrue morgue\nparis 75013"}];
}
},
});
@@ -565,9 +565,9 @@ QUnit.module("Fields", (hooks) => {
`,
- mockRPC(route, { kwargs, method, model }) {
- if (method === "name_get" && kwargs.context.show_address) {
- return [[2, "second record\nrue morgue\nparis 75013"]];
+ mockRPC(route, { kwargs, method, args }) {
+ if (method === "read" && args[1].length === 1 && args[1][0] === "display_name" && kwargs.context.show_address) {
+ return [{id: 2, display_name: "second record\nrue morgue\nparis 75013"}];
}
},
});
@@ -1429,9 +1429,9 @@ QUnit.module("Fields", (hooks) => {
`,
mockRPC(route, { args, kwargs, method }) {
- if (method === "name_get") {
+ if (method === "read" && args[1].length === 1 && args[1][0] === "display_name") {
assert.step(method);
- return args.map((id) => [id, namegets[id]]);
+ return args.map((id) => ({id, display_name: namegets[id]}));
}
if (method === "name_search") {
assert.step(method);
@@ -1439,7 +1439,7 @@ QUnit.module("Fields", (hooks) => {
}
},
});
- assert.verifySteps(["name_get"]);
+ assert.verifySteps(["read"]);
const input = target.querySelector(".o_field_widget input");
@@ -1463,7 +1463,7 @@ QUnit.module("Fields", (hooks) => {
await click(target.querySelector(".dropdown-menu li"));
// Check the selection has been taken into account
- assert.verifySteps(["name_get"]);
+ assert.verifySteps(["read"]);
assert.strictEqual(input.value, "fizz");
assert.strictEqual(
target.querySelector(".o_field_many2one_extra").innerHTML,
@@ -1541,15 +1541,15 @@ QUnit.module("Fields", (hooks) => {
`,
- mockRPC(route, { method }) {
- if (method === "name_get") {
+ mockRPC(route, { method, args }) {
+ if (method === "read" && args[1].length === 1 && args[1][0] === "display_name") {
count++;
- return Promise.resolve([[1, "first record\nand some address"]]);
+ return Promise.resolve([{id: 1, display_name: "first record\nand some address"}]);
}
},
});
- assert.strictEqual(count, 1, "an extra name_get should have been done");
+ assert.strictEqual(count, 1, "an extra read should have been done");
assert.ok(
target.querySelector("a.o_form_uri").textContent.includes("and some address"),
"should display additional result"
@@ -1568,15 +1568,15 @@ QUnit.module("Fields", (hooks) => {
`,
- mockRPC(route, { method }) {
- if (method === "name_get") {
+ mockRPC(route, { method, args }) {
+ if (method === "read" && args[1].length === 1 && args[1][0] === "display_name") {
count++;
- return Promise.resolve([[1, "first record\nand some address"]]);
+ return Promise.resolve([{id: 1, display_name: "first record\nand some address"}]);
}
},
});
- assert.strictEqual(count, 1, "an extra name_get should have been done");
+ assert.strictEqual(count, 1, "an extra read should have been done");
assert.strictEqual(
target.querySelector(".o_field_widget[name='trululu'] input").value,
"first record",
@@ -1986,9 +1986,9 @@ QUnit.module("Fields", (hooks) => {
`,
- mockRPC(route, { method }) {
- if (method === "name_get") {
- throw new Error("Nameget should not be called");
+ mockRPC(route, { method, args}) {
+ if (method === "read" && args[1].length === 1 && args[1][0] === "display_name") {
+ throw new Error("read(['display_name']) should not be called");
}
},
});
@@ -2025,9 +2025,9 @@ QUnit.module("Fields", (hooks) => {
`,
- mockRPC(route, { method }) {
- if (method === "name_get") {
- throw new Error("Nameget should not be called");
+ mockRPC(route, { method, args }) {
+ if (method === "read" && args[1].length === 1 && args[1][0] === "display_name") {
+ throw new Error("read(['display_name']) should not be called");
}
},
});
@@ -2115,7 +2115,7 @@ QUnit.module("Fields", (hooks) => {
}
);
- QUnit.test("list in form: name_get with unique ids (default_get)", async function (assert) {
+ QUnit.test("list in form: read with unique ids (default_get)", async function (assert) {
serverData.models.partner.records[0].display_name = "MyTrululu";
serverData.models.partner.fields.p.default = [
[0, 0, { trululu: 1, p: [] }],
@@ -2136,9 +2136,9 @@ QUnit.module("Fields", (hooks) => {
`,
- mockRPC(route, { method }) {
- if (method === "name_get") {
- throw new Error("should not call name_get");
+ mockRPC(route, { method, args }) {
+ if (method === "read" && args[1].length === 1 && args[1][0] === "display_name") {
+ throw new Error("read(['display_name']) should not called");
}
},
});
@@ -2838,16 +2838,16 @@ QUnit.module("Fields", (hooks) => {
`,
mockRPC(route, { args, method }) {
count++;
- if (method === "name_get" && args[0] === 2) {
+ if (method === "read" && args[1].length === 1 && args[1][0] === "display_name" && args[0] === 2) {
// LPE: any call_kw route can take either [ids] or id as the first
// argument as model.browse() in python supports both
- // With the basic_model, name_get is passed only an id, not an array
- return Promise.resolve([[2, "hello world\nso much noise"]]);
+ // With the basic_model, read is passed only an id, not an array
+ return Promise.resolve([{id: 2, display_name: "hello world\nso much noise"}]);
}
},
});
- assert.strictEqual(count, 3, "should have done 3 rpcs (get_views, onchange and name_get)");
+ assert.strictEqual(count, 3, "should have done 3 rpcs (get_views, onchange and read)");
assert.strictEqual(
target.querySelector(".o_field_widget[name='trululu'] input").value,
"hello world",
diff --git a/addons/web/static/tests/views/fields/one2many_field_tests.js b/addons/web/static/tests/views/fields/one2many_field_tests.js
index 6fa48613b16..71c11f3b1c4 100644
--- a/addons/web/static/tests/views/fields/one2many_field_tests.js
+++ b/addons/web/static/tests/views/fields/one2many_field_tests.js
@@ -275,7 +275,7 @@ QUnit.module("Fields", (hooks) => {
await clickCreate(target);
// change the int_field through drag and drop
- // that way, we'll trigger the sorting and the name_get
+ // that way, we'll trigger the sorting and the display_name read
// of the lines of "p"
await dragAndDrop("tbody tr:nth-child(2) .o_handle_cell", "tbody tr", "top");
@@ -1728,11 +1728,11 @@ QUnit.module("Fields", (hooks) => {
`,
mockRPC(route, args) {
- if (checkRPC && args.method === "name_get") {
+ if (checkRPC && args.method === "read" && args.args[1].length === 1 && args.args[1][0] === "display_name") {
assert.deepEqual(
args.args[0],
[37],
- "should only fetch the name_get of the unknown record"
+ "should only fetch the display_name of the unknown record"
);
}
},
@@ -8794,7 +8794,7 @@ QUnit.module("Fields", (hooks) => {
);
QUnit.test(
- "one2many with sequence field, fetch name_get from empty list, field text",
+ "one2many with sequence field, fetch display from empty list, field text",
async function (assert) {
// There was a bug where a RPC would fail because no route was set.
// The scenario is:
@@ -8803,7 +8803,7 @@ QUnit.module("Fields", (hooks) => {
// - a handle field
// - a many2one, which is not required, and we will leave it empty
// - reorder the lines with the handle
- // -> This will call a resequence, which calls a name_get.
+ // -> This will call a resequence, which calls a display_name read.
// -> With the bug that would fail, if it's ok the test will pass.
// This test will also make sure lists with
@@ -11124,7 +11124,7 @@ QUnit.module("Fields", (hooks) => {
await addRow(target);
});
- QUnit.test("do not call name_get if display_name already known", async function (assert) {
+ QUnit.test("do not call read if display_name already known", async function (assert) {
serverData.models.partner.fields.product_id.default = 37;
serverData.models.partner.onchanges = {
trululu: function (obj) {
diff --git a/addons/web/static/tests/views/fields/reference_field_tests.js b/addons/web/static/tests/views/fields/reference_field_tests.js
index 52ddceca89f..43e25a10b03 100644
--- a/addons/web/static/tests/views/fields/reference_field_tests.js
+++ b/addons/web/static/tests/views/fields/reference_field_tests.js
@@ -253,7 +253,7 @@ QUnit.module("Fields", (hooks) => {
"name_create",
"create",
"read",
- "name_get",
+ "read",
],
"The name_create method should have been called"
);
@@ -612,14 +612,14 @@ QUnit.module("Fields", (hooks) => {
`,
- mockRPC(route, { method, model }) {
- if (method === "name_get") {
+ mockRPC(route, { method, model, args }) {
+ if (method === "read" && args[1].length === 1 && args[1][0] === "display_name") {
assert.step(model);
}
},
});
- assert.verifySteps(["product"], "the first name_get should have been done");
+ assert.verifySteps(["product"], "the first display_name read should have been done");
assert.strictEqual(
target.querySelector(".o_field_widget[name='reference'] select").value,
"product",
@@ -634,7 +634,7 @@ QUnit.module("Fields", (hooks) => {
// trigger onchange
await editInput(target, ".o_field_widget[name=int_field] input", 12);
- assert.verifySteps(["partner_type"], "the second name_get should have been done");
+ assert.verifySteps(["partner_type"], "the second display_name read should have been done");
assert.strictEqual(
target.querySelector(".o_field_widget[name='reference'] select").value,
"partner_type",
@@ -705,14 +705,14 @@ QUnit.module("Fields", (hooks) => {
`,
- mockRPC(route, { model, method }) {
- if (model === "product" && method === "name_get") {
+ mockRPC(route, { model, method, args }) {
+ if (model === "product" && method === "read" && args[1].length === 1 && args[1][0] === "display_name") {
nbNameGet++;
}
},
});
- assert.strictEqual(nbNameGet, 1, "the first name_get should have been done");
+ assert.strictEqual(nbNameGet, 1, "the first display_name read should have been done");
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo]").textContent,
"xphone",
@@ -722,7 +722,7 @@ QUnit.module("Fields", (hooks) => {
// trigger onchange
await editInput(target, ".o_field_widget[name=int_field] input", 41);
- assert.strictEqual(nbNameGet, 2, "the second name_get should have been done");
+ assert.strictEqual(nbNameGet, 2, "the second display_name read should have been done");
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo]").textContent,
"xpad",
diff --git a/addons/web/static/tests/views/form/form_view_tests.js b/addons/web/static/tests/views/form/form_view_tests.js
index c6ab1527b24..07643c5340f 100644
--- a/addons/web/static/tests/views/form/form_view_tests.js
+++ b/addons/web/static/tests/views/form/form_view_tests.js
@@ -3837,7 +3837,7 @@ QUnit.module("Views", (hooks) => {
`,
mockRPC(route, args) {
- if (args.method === "name_get") {
+ if (args.method === 'read' && args.args[1].length === 1 && args.args[1][0] === 'display_name') {
nameGetCount++;
}
},
@@ -3868,8 +3868,8 @@ QUnit.module("Views", (hooks) => {
serverData,
arch: '
',
mockRPC(route, args) {
- if (args.method === "name_get") {
- throw new Error("Should not call name_get");
+ if (args.method === 'read' && args.args[1].length === 1 && args.args[1][0] === 'display_name') {
+ throw new Error("Should not call display_name read");
}
},
});
diff --git a/addons/web/static/tests/views/kanban/kanban_view_tests.js b/addons/web/static/tests/views/kanban/kanban_view_tests.js
index 00891ffd95e..58a09a3d760 100644
--- a/addons/web/static/tests/views/kanban/kanban_view_tests.js
+++ b/addons/web/static/tests/views/kanban/kanban_view_tests.js
@@ -4809,11 +4809,11 @@ QUnit.module("Views", (hooks) => {
"web_read_group",
"web_search_read",
"web_search_read",
- "name_get",
+ "read",
"web_read_group",
"web_search_read",
"web_search_read",
- "name_get",
+ "read",
]);
});
diff --git a/addons/web/static/tests/views/list_view_tests.js b/addons/web/static/tests/views/list_view_tests.js
index eeb98f53114..39dcdfef094 100644
--- a/addons/web/static/tests/views/list_view_tests.js
+++ b/addons/web/static/tests/views/list_view_tests.js
@@ -10750,7 +10750,7 @@ QUnit.module("Views", (hooks) => {
serverData,
arch: '',
mockRPC(route, args) {
- if (args.method === "name_get") {
+ if (args.method === "read") {
assert.step(args.model);
}
},
@@ -10758,7 +10758,7 @@ QUnit.module("Views", (hooks) => {
assert.verifySteps(
["bar", "res_currency"],
- "should have done 1 name_get by model in reference values"
+ "should have done 1 read by model in reference values"
);
assert.strictEqual(
$(target).find("tbody td:not(.o_list_record_selector)").text(),
@@ -10791,7 +10791,7 @@ QUnit.module("Views", (hooks) => {
groupBy: ["foo"],
mockRPC(route, args) {
assert.step(args.method || route);
- if (args.method === "name_get") {
+ if (args.method === 'read' && args.args[1].length === 1 && args.args[1][0] === 'display_name') {
if (args.model === "bar") {
assert.deepEqual(args.args[0], [1, 2, 3]);
}
@@ -10801,7 +10801,7 @@ QUnit.module("Views", (hooks) => {
}
},
});
- assert.verifySteps(["get_views", "web_read_group", "name_get", "name_get"]);
+ assert.verifySteps(["get_views", "web_read_group", "read", "read"]);
assert.containsN(target, ".o_group_header", 2);
const allNames = Array.from(
target.querySelectorAll(".o_data_cell"),
@@ -10876,7 +10876,7 @@ QUnit.module("Views", (hooks) => {
if (args.method === "write") {
assert.deepEqual(args.args, [[1, 2, 3], { bar: true }]);
}
- if (args.method === "name_get") {
+ if (args.method === 'read' && args.args[1].length === 1 && args.args[1][0] === 'display_name') {
if (nameGetCount === 2) {
assert.strictEqual(args.model, "bar");
assert.deepEqual(args.args[0], [1, 2]);
@@ -10890,7 +10890,7 @@ QUnit.module("Views", (hooks) => {
},
});
- assert.verifySteps(["get_views", "web_read_group", "name_get", "name_get"]);
+ assert.verifySteps(["get_views", "web_read_group", "read", "read"]);
await click(target.querySelectorAll(".o_data_row .o_list_record_selector input")[0]);
await click(target.querySelectorAll(".o_data_row .o_list_record_selector input")[1]);
await click(target.querySelectorAll(".o_data_row .o_list_record_selector input")[2]);
@@ -10899,7 +10899,7 @@ QUnit.module("Views", (hooks) => {
await click(target, ".modal .modal-footer .btn-primary");
assert.containsNone(target, ".modal");
- assert.verifySteps(["write", "read", "name_get", "name_get"]);
+ assert.verifySteps(["write", "read", "read", "read"]);
assert.containsN(target, ".o_group_header", 2);
const allNames = Array.from(target.querySelectorAll(".o_data_cell"))
@@ -17833,8 +17833,8 @@ QUnit.module("Views", (hooks) => {
`,
mockRPC(_, args) {
- if (args.method === "name_get") {
- assert.step("name_get");
+ if (args.method === 'read' && args.args[1].length === 1 && args.args[1][0] === 'display_name') {
+ assert.step("readDisplayName");
assert.deepEqual(args.args[0], [3]);
}
},
@@ -17853,7 +17853,7 @@ QUnit.module("Views", (hooks) => {
await click(target, ".modal .o_data_row:nth-child(3) td[name=display_name]");
- assert.verifySteps(["name_get"]);
+ assert.verifySteps(["readDisplayName"]);
await clickSave(target);
assert.deepEqual(
diff --git a/addons/web/static/tests/views/record_tests.js b/addons/web/static/tests/views/record_tests.js
index 1c47aa11ee4..aad8b33ec9d 100644
--- a/addons/web/static/tests/views/record_tests.js
+++ b/addons/web/static/tests/views/record_tests.js
@@ -326,7 +326,7 @@ QUnit.module("Record Component", (hooks) => {
},
}),
});
- assert.verifySteps(["/web/dataset/call_kw/bar/name_get"]);
+ assert.verifySteps(["/web/dataset/call_kw/bar/read"]);
assert.strictEqual(target.querySelector(".o_field_many2one_selection input").value, "bar1");
await editInput(target, ".o_field_many2one_selection input", "abc");
assert.verifySteps(["/web/dataset/call_kw/bar/name_search"]);
diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py
index f5e2894fe13..62bcb90296c 100644
--- a/addons/website/models/ir_ui_view.py
+++ b/addons/website/models/ir_ui_view.py
@@ -69,19 +69,17 @@ class View(models.Model):
raise ValueError(f"Trying to create a view for website {new_website_id} from a website {website_id} environment")
return super().create(vals_list)
- def name_get(self):
+ def _compute_display_name(self):
if not (self._context.get('display_key') or self._context.get('display_website')):
- return super(View, self).name_get()
+ return super()._compute_display_name()
- res = []
for view in self:
view_name = view.name
if self._context.get('display_key'):
view_name += ' <%s>' % view.key
if self._context.get('display_website') and view.website_id:
view_name += ' [%s]' % view.website_id.name
- res.append((view.id, view_name))
- return res
+ view.display_name = view_name
def write(self, vals):
'''COW for ir.ui.view. This way editing websites does not impact other
diff --git a/addons/website/models/res_partner.py b/addons/website/models/res_partner.py
index d549cad59dd..61b925f8474 100644
--- a/addons/website/models/res_partner.py
+++ b/addons/website/models/res_partner.py
@@ -3,7 +3,7 @@
import werkzeug.urls
-from odoo import models, fields
+from odoo import models, fields, api
class Partner(models.Model):
_name = 'res.partner'
@@ -31,13 +31,11 @@ class Partner(models.Model):
}
return 'https://maps.google.com/maps?' + werkzeug.urls.url_encode(params)
- def _get_name(self):
- name = super(Partner, self)._get_name()
- if self._context.get('display_website') and self.env.user.has_group('website.group_multi_website'):
- if self.website_id:
- name += ' [%s]' % self.website_id.name
- return name
-
+ @api.depends_context('display_website')
def _compute_display_name(self):
- self2 = self.with_context(display_website=False)
- super(Partner, self2)._compute_display_name()
+ super()._compute_display_name()
+ if not self._context.get('display_website') or not self.env.user.has_group('website.group_multi_website'):
+ return
+ for partner in self:
+ if partner.website_id:
+ partner.display_name += f' [{self.website_id.name}]'
diff --git a/addons/website/models/website_menu.py b/addons/website/models/website_menu.py
index 83bedf697a0..5c668cd034e 100644
--- a/addons/website/models/website_menu.py
+++ b/addons/website/models/website_menu.py
@@ -52,17 +52,15 @@ class Menu(models.Model):
mega_menu_content = fields.Html(translate=html_translate, sanitize=False, prefetch=True)
mega_menu_classes = fields.Char()
- def name_get(self):
+ def _compute_display_name(self):
if not self._context.get('display_website') and not self.env.user.has_group('website.group_multi_website'):
- return super(Menu, self).name_get()
+ return super()._compute_display_name()
- res = []
for menu in self:
menu_name = menu.name
if menu.website_id:
- menu_name += ' [%s]' % menu.website_id.name
- res.append((menu.id, menu_name))
- return res
+ menu_name += f' [{menu.website_id.name}]'
+ menu.display_name = menu_name
@api.model_create_multi
def create(self, vals_list):
diff --git a/addons/website/models/website_rewrite.py b/addons/website/models/website_rewrite.py
index 2e393904203..bbb926e0025 100644
--- a/addons/website/models/website_rewrite.py
+++ b/addons/website/models/website_rewrite.py
@@ -103,12 +103,9 @@ class WebsiteRewrite(models.Model):
except ValueError as e:
raise ValidationError(_('"URL to" is invalid: %s') % e)
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for rewrite in self:
- name = "%s - %s" % (rewrite.redirect_type, rewrite.name)
- result.append((rewrite.id, name))
- return result
+ rewrite.display_name = f"{rewrite.redirect_type} - {rewrite.name}"
@api.model_create_multi
def create(self, vals_list):
diff --git a/addons/website/models/website_visitor.py b/addons/website/models/website_visitor.py
index e8c2b9fdb93..81fdcfee277 100644
--- a/addons/website/models/website_visitor.py
+++ b/addons/website/models/website_visitor.py
@@ -84,14 +84,9 @@ class WebsiteVisitor(models.Model):
]
@api.depends('partner_id')
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for record in self:
- res.append((
- record.id,
- record.partner_id.name or _('Website Visitor #%s', record.id)
- ))
- return res
+ record.display_name = record.partner_id.name or _('Website Visitor #%s', record.id)
@api.depends('access_token')
def _compute_partner_id(self):
diff --git a/addons/website_event/models/event_registration_answer.py b/addons/website_event/models/event_registration_answer.py
index b78590cd1ca..2d5817928fb 100644
--- a/addons/website_event/models/event_registration_answer.py
+++ b/addons/website_event/models/event_registration_answer.py
@@ -25,10 +25,6 @@ class EventRegistrationAnswer(models.Model):
]
# for displaying selected answers by attendees in attendees list view
- def name_get(self):
- return [
- (reg.id,
- reg.value_answer_id.name if reg.question_type == "simple_choice" else reg.value_text_box
- )
- for reg in self
- ]
+ def _compute_display_name(self):
+ for reg in self:
+ reg.display_name = reg.value_answer_id.name if reg.question_type == "simple_choice" else reg.value_text_box
diff --git a/addons/website_event/models/website_visitor.py b/addons/website_event/models/website_visitor.py
index 9b2a9d5c685..70d009bc5bf 100644
--- a/addons/website_event/models/website_visitor.py
+++ b/addons/website_event/models/website_visitor.py
@@ -21,15 +21,14 @@ class WebsiteVisitor(models.Model):
search="_search_event_registered_ids",
groups="event.group_event_registration_desk")
- @api.depends('partner_id, event_registration_ids.name')
- def name_get(self):
+ @api.depends('partner_id', 'event_registration_ids.name')
+ def _compute_display_name(self):
""" If there is an event registration for an anonymous visitor, use that
registered attendee name as visitor name. """
- res_dict = dict(super().name_get())
+ super()._compute_display_name()
# sudo is needed for `event_registration_ids`
for visitor in self.sudo().filtered(lambda v: not v.partner_id and v.event_registration_ids):
- res_dict[visitor.id] = visitor.event_registration_ids[-1].name
- return list(res_dict.items())
+ visitor.display_name = visitor.event_registration_ids[-1].name
@api.depends('event_registration_ids')
def _compute_event_registration_count(self):
diff --git a/addons/website_google_map/controllers/main.py b/addons/website_google_map/controllers/main.py
index fd5528fb6d1..1d3d9fe7dcf 100644
--- a/addons/website_google_map/controllers/main.py
+++ b/addons/website_google_map/controllers/main.py
@@ -40,7 +40,7 @@ class GoogleMap(http.Controller):
partner_data["partners"].append({
'id': partner.id,
'name': partner.name,
- 'address': '\n'.join(partner.name_get()[0][1].split('\n')[1:]),
+ 'address': '\n'.join(partner.display_name.split('\n')[1:]),
'latitude': str(partner.partner_latitude) if partner.partner_latitude else False,
'longitude': str(partner.partner_longitude) if partner.partner_longitude else False,
})
diff --git a/addons/website_hr_recruitment/models/hr_department.py b/addons/website_hr_recruitment/models/hr_department.py
index 1a983340246..4e5befdc28d 100644
--- a/addons/website_hr_recruitment/models/hr_department.py
+++ b/addons/website_hr_recruitment/models/hr_department.py
@@ -1,14 +1,11 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from odoo import models
+from odoo import models, fields
class Department(models.Model):
_inherit = 'hr.department'
- def name_get(self):
- # Get department name using superuser, because model is not accessible
- # for portal users
- self_sudo = self.sudo()
- return super(Department, self_sudo).name_get()
+ # Get department name using superuser, because model is not accessible for portal users
+ display_name = fields.Char(compute_sudo=True)
diff --git a/addons/website_sale/models/product_public_category.py b/addons/website_sale/models/product_public_category.py
index b32eef093d1..618c721370f 100644
--- a/addons/website_sale/models/product_public_category.py
+++ b/addons/website_sale/models/product_public_category.py
@@ -37,11 +37,9 @@ class ProductPublicCategory(models.Model):
if not self._check_recursion():
raise ValueError(_('Error! You cannot create recursive categories.'))
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for category in self:
- res.append((category.id, " / ".join(category.parents_and_self.mapped('name'))))
- return res
+ category.display_name = " / ".join(category.parents_and_self.mapped('name'))
def _compute_parents_and_self(self):
for category in self:
diff --git a/addons/website_sale/models/product_ribbon.py b/addons/website_sale/models/product_ribbon.py
index 9d23f9e054f..a8c36699322 100644
--- a/addons/website_sale/models/product_ribbon.py
+++ b/addons/website_sale/models/product_ribbon.py
@@ -8,8 +8,9 @@ class ProductRibbon(models.Model):
_name = "product.ribbon"
_description = 'Product ribbon'
- def name_get(self):
- return [(ribbon.id, '%s (#%d)' % (tools.html2plaintext(ribbon.html), ribbon.id)) for ribbon in self]
+ def _compute_display_name(self):
+ for ribbon in self:
+ ribbon.display_name = f'{tools.html2plaintext(ribbon.html)} (#{ribbon.id})'
html = fields.Html(string='Ribbon html', required=True, translate=True, sanitize=False)
bg_color = fields.Char(string='Ribbon background color', required=False)
diff --git a/odoo/addons/base/models/ir_fields.py b/odoo/addons/base/models/ir_fields.py
index ba7345a09f2..38c37e7e104 100644
--- a/odoo/addons/base/models/ir_fields.py
+++ b/odoo/addons/base/models/ir_fields.py
@@ -398,7 +398,7 @@ class IrFieldsConverter(models.AbstractModel):
:param model: model to which the field belongs
:param field: relational field for which references are provided
:param subfield: a relational subfield allowing building of refs to
- existing records: ``None`` for a name_get/name_search,
+ existing records: ``None`` for a name_search,
``id`` for an external id and ``.id`` for a database
id
:param value: value of the reference to match to an actual record
@@ -542,7 +542,7 @@ class IrFieldsConverter(models.AbstractModel):
:return: the record subfield to use for referencing and a list of warnings
:rtype: str, list
"""
- # Can import by name_get, external id or database id
+ # Can import by display_name, external id or database id
fieldset = set(record)
if fieldset - REFERENCING_FIELDS:
raise ValueError(
diff --git a/odoo/addons/base/models/ir_model.py b/odoo/addons/base/models/ir_model.py
index 9ebb847bdc1..6bafbf7d646 100644
--- a/odoo/addons/base/models/ir_model.py
+++ b/odoo/addons/base/models/ir_model.py
@@ -371,11 +371,11 @@ class IrModel(models.Model):
@api.model
def name_create(self, name):
""" Infer the model from the name. E.g.: 'My New Model' should become 'x_my_new_model'. """
- vals = {
+ ir_model = self.create({
'name': name,
'model': 'x_' + '_'.join(name.lower().split(' ')),
- }
- return self.create(vals).name_get()[0]
+ })
+ return ir_model.id, ir_model.display_name
def _reflect_model_params(self, model):
""" Return the values to write to the database for the given model. """
@@ -1042,11 +1042,9 @@ class IrModelFields(models.Model):
self.clear_caches()
return res
- def name_get(self):
- res = []
+ def _compute_display_name(self):
for field in self:
- res.append((field.id, '%s (%s)' % (field.field_description, field.model)))
- return res
+ field.display_name = f'{field.field_description} ({field.model})'
def _reflect_field_params(self, field, model_id):
""" Return the values to write to the database for the given field. """
@@ -1998,22 +1996,14 @@ class IrModelData(models.Model):
self._table, ['model', 'res_id'])
return res
- def name_get(self):
- model_id_name = defaultdict(dict) # {res_model: {res_id: name}}
- for xid in self:
- model_id_name[xid.model][xid.res_id] = None
-
- # fill in model_id_name with name_get() of corresponding records
- for model, id_name in model_id_name.items():
- try:
- ng = self.env[model].browse(id_name).name_get()
- id_name.update(ng)
- except Exception:
- pass
-
- # return results, falling back on complete_name
- return [(xid.id, model_id_name[xid.model][xid.res_id] or xid.complete_name)
- for xid in self]
+ def _compute_display_name(self):
+ for model, model_data_records in self.grouped('model').items():
+ records = self.env[model].browse(model_data_records.mapped('res_id'))
+ for xid, target_record in zip(model_data_records, records):
+ try:
+ xid.display_name = target_record.display_name or xid.complete_name
+ except Exception: # pylint: disable=broad-except
+ xid.display_name = xid.complete_name
# NEW V8 API
@api.model
diff --git a/odoo/addons/base/models/ir_qweb_fields.py b/odoo/addons/base/models/ir_qweb_fields.py
index dbb2f47520b..c1b68aaeef6 100644
--- a/odoo/addons/base/models/ir_qweb_fields.py
+++ b/odoo/addons/base/models/ir_qweb_fields.py
@@ -777,16 +777,15 @@ class Contact(models.AbstractModel):
opsep = Markup('
')
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
+ # display_name = 'Foo\n \n' -> This is a res.partner with a name and no address
# That would return markup('
') 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()
+ if any(elem.strip() for elem in value.display_name.split("\n")[1:]):
+ address = opsep.join(value.display_name.split("\n")[1:]).strip()
else:
address = ''
val = {
- 'name': name_get.split("\n")[0],
+ 'name': value.display_name.split("\n")[0],
'address': address,
'phone': value.phone,
'mobile': value.mobile,
diff --git a/odoo/addons/base/models/ir_ui_menu.py b/odoo/addons/base/models/ir_ui_menu.py
index 132ad93e1d2..038c879ab15 100644
--- a/odoo/addons/base/models/ir_ui_menu.py
+++ b/odoo/addons/base/models/ir_ui_menu.py
@@ -155,8 +155,9 @@ class IrUiMenu(models.Model):
# to be consistent with search() above
return len(self.search(domain, limit=limit))
- def name_get(self):
- return [(menu.id, menu._get_full_name()) for menu in self]
+ def _compute_display_name(self):
+ for menu in self:
+ menu.display_name = menu._get_full_name()
@api.model_create_multi
def create(self, vals_list):
diff --git a/odoo/addons/base/models/res_bank.py b/odoo/addons/base/models/res_bank.py
index 3f43eaef8ae..73d40b189d9 100644
--- a/odoo/addons/base/models/res_bank.py
+++ b/odoo/addons/base/models/res_bank.py
@@ -30,12 +30,10 @@ class Bank(models.Model):
active = fields.Boolean(default=True)
bic = fields.Char('Bank Identifier Code', index=True, help="Sometimes called BIC or Swift.")
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for bank in self:
name = (bank.name or '') + (bank.bic and (' - ' + bank.bic) or '')
- result.append((bank.id, name))
- return result
+ bank.display_name = name
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
@@ -113,9 +111,9 @@ class ResPartnerBank(models.Model):
"""
return 'bank'
- def name_get(self):
- return [(acc.id, '{} - {}'.format(acc.acc_number, acc.bank_id.name) if acc.bank_id else acc.acc_number)
- for acc in self]
+ def _compute_display_name(self):
+ for acc in self:
+ acc.display_name = f'{acc.acc_number} - {acc.bank_id.name}' if acc.bank_id else acc.acc_number
@api.model
def _search(self, domain, offset=0, limit=None, order=None, access_rights_uid=None):
diff --git a/odoo/addons/base/models/res_config.py b/odoo/addons/base/models/res_config.py
index b23eda027e5..3dd883f15c1 100644
--- a/odoo/addons/base/models/res_config.py
+++ b/odoo/addons/base/models/res_config.py
@@ -639,12 +639,11 @@ class ResConfigSettings(models.TransientModel, ResConfigModuleInstallationMixin)
return actions.read()[0]
return {}
- def name_get(self):
- """ Override name_get method to return an appropriate configuration wizard
+ def _compute_display_name(self):
+ """ Override display_name method to return an appropriate configuration wizard
name, and not the generated name."""
action = self.env['ir.actions.act_window'].search([('res_model', '=', self._name)], limit=1)
- name = action.name or self._name
- return [(record.id, name) for record in self]
+ self.display_name = action.name or self._name
@api.model
def get_option_path(self, menu_xml_id):
diff --git a/odoo/addons/base/models/res_country.py b/odoo/addons/base/models/res_country.py
index 94c44036116..fd4654e7250 100644
--- a/odoo/addons/base/models/res_country.py
+++ b/odoo/addons/base/models/res_country.py
@@ -193,8 +193,6 @@ class CountryState(models.Model):
if state_id not in first_state_ids
]
- def name_get(self):
- result = []
+ def _compute_display_name(self):
for record in self:
- result.append((record.id, "{} ({})".format(record.name, record.country_id.code)))
- return result
+ record.display_name = f"{record.name} ({record.country_id.code})"
diff --git a/odoo/addons/base/models/res_currency.py b/odoo/addons/base/models/res_currency.py
index 3a1a553ee3d..a28d66a1a1a 100644
--- a/odoo/addons/base/models/res_currency.py
+++ b/odoo/addons/base/models/res_currency.py
@@ -156,9 +156,6 @@ class Currency(models.Model):
for currency in self:
currency.date = currency.rate_ids[:1].name
- def name_get(self):
- return [(currency.id, tools.ustr(currency.name)) for currency in self]
-
def amount_to_text(self, amount):
self.ensure_one()
def _num2words(number, lang):
diff --git a/odoo/addons/base/models/res_partner.py b/odoo/addons/base/models/res_partner.py
index 380068174eb..da51c8c358a 100644
--- a/odoo/addons/base/models/res_partner.py
+++ b/odoo/addons/base/models/res_partner.py
@@ -128,25 +128,23 @@ class PartnerCategory(models.Model):
if not self._check_recursion():
raise ValidationError(_('You can not create recursive tags.'))
- def name_get(self):
+ def _compute_display_name(self):
""" Return the categories' display name, including their direct
parent by default.
"""
- res = []
for category in self:
names = []
current = category
while current:
names.append(current.name)
current = current.parent_id
- res.append((category.id, ' / '.join(reversed(names))))
- return res
+ category.display_name = ' / '.join(reversed(names))
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
domain = domain or []
if name:
- # Be sure name_search is symetric to name_get
+ # Be sure name_search is symetric to display_name
name = name.split(' / ')[-1]
domain = [('name', operator, name)] + domain
return self._search(domain, limit=limit, order=order)
@@ -165,8 +163,11 @@ class Partner(models.Model):
_description = 'Contact'
_inherit = ['format.address.mixin', 'avatar.mixin']
_name = "res.partner"
- _order = "display_name, id"
- _rec_names_search = ['display_name', 'email', 'ref', 'vat', 'company_registry'] # TODO vat must be sanitized the same way for storing/searching
+ _order = "complete_name, id"
+ _rec_names_search = ['complete_name', 'email', 'ref', 'vat', 'company_registry'] # TODO vat must be sanitized the same way for storing/searching
+
+ # the partner types that must be added to a partner's complete name, like "Delivery"
+ _complete_name_displayed_types = ('invoice', 'delivery', 'other')
def _default_category(self):
return self.env['res.partner.category'].browse(self._context.get('category_id'))
@@ -189,7 +190,7 @@ class Partner(models.Model):
return values
name = fields.Char(index=True, default_export_compatible=True)
- display_name = fields.Char(compute='_compute_display_name', recursive=True, store=True, index=True)
+ complete_name = fields.Char(compute='_compute_complete_name', store=True, index=True)
date = fields.Date(index=True)
title = fields.Many2one('res.partner.title')
parent_id = fields.Many2one('res.partner', string='Related Company', index=True)
@@ -332,12 +333,22 @@ class Partner(models.Model):
return "base/static/img/money.png"
return super()._avatar_get_placeholder_path()
- @api.depends('is_company', 'name', 'parent_id.display_name', 'type', 'company_name', 'commercial_company_name')
- def _compute_display_name(self):
- # retrieve name_get() without any fancy feature
- names = dict(self.with_context({}).name_get())
+ @api.depends('is_company', 'name', 'parent_id.name', 'type', 'company_name', 'commercial_company_name')
+ def _compute_complete_name(self):
+ displayed_types = self._complete_name_displayed_types
+ # determine the labels of partner types to be included
+ # as 'displayed_types' (without user lang to avoid context dependency)
+ type_description = dict(self._fields['type']._description_selection(self.with_context({}).env))
+
for partner in self:
- partner.display_name = names.get(partner.id)
+ name = partner.name or ''
+ if partner.company_name or partner.parent_id:
+ if not name and partner.type in displayed_types:
+ name = type_description[partner.type]
+ if not partner.is_company:
+ name = f"{partner.commercial_company_name or partner.sudo().parent_id.name}, {name}"
+
+ partner.complete_name = name.strip()
@api.depends('lang')
def _compute_active_lang_count(self):
@@ -803,39 +814,25 @@ class Partner(models.Model):
'target': 'new',
}
- def _get_contact_name(self, partner, name):
- return "%s, %s" % (partner.commercial_company_name or partner.sudo().parent_id.name, name)
-
- def _get_name(self):
- """ Utility method to allow name_get to be overrided without re-browse the partner """
- partner = self
- name = partner.name or ''
-
- if partner.company_name or partner.parent_id:
- if not name and partner.type in ['invoice', 'delivery', 'other']:
- name = dict(self.fields_get(['type'])['type']['selection'])[partner.type]
- if not partner.is_company:
- name = self._get_contact_name(partner, name)
- if self._context.get('show_address'):
- name = name + "\n" + partner._display_address(without_company=True)
- name = re.sub(r'\s+\n', '\n', name)
- if self._context.get('partner_show_db_id'):
- name = "%s (%s)" % (name, partner.id)
- if self._context.get('address_inline'):
- splitted_names = name.split("\n")
- name = ", ".join([n for n in splitted_names if n.strip()])
- if self._context.get('show_email') and partner.email:
- name = "%s <%s>" % (name, partner.email)
- if self._context.get('show_vat') and partner.vat:
- name = "%s ‒ %s" % (name, partner.vat)
- return name.strip()
-
- def name_get(self):
- res = []
+ @api.depends('complete_name')
+ @api.depends_context('show_address', 'partner_show_db_id', 'address_inline', 'show_email', 'show_vat')
+ def _compute_display_name(self):
for partner in self:
- name = partner._get_name()
- res.append((partner.id, name))
- return res
+ name = partner.complete_name
+ if partner._context.get('show_address'):
+ name = name + "\n" + partner._display_address(without_company=True)
+ name = re.sub(r'\s+\n', '\n', name)
+ if partner._context.get('partner_show_db_id'):
+ name = f"{name} ({partner.id})"
+ if partner._context.get('address_inline'):
+ splitted_names = name.split("\n")
+ name = ", ".join([n for n in splitted_names if n.strip()])
+ if partner._context.get('show_email') and partner.email:
+ name = f"{name} <{partner.email}>"
+ if partner._context.get('show_vat') and partner.vat:
+ name = f"{name} ‒ {partner.vat}"
+
+ partner.display_name = name.strip()
def _parse_partner_name(self, text):
""" Parse partner name (given by text) in order to find a name and an
@@ -891,7 +888,7 @@ class Partner(models.Model):
if email: # keep default_email in context
create_values['email'] = email
partner = self.create(create_values)
- return partner.name_get()[0]
+ return partner.id, partner.display_name
@api.model
def _search(self, domain, offset=0, limit=None, order=None, access_rights_uid=None):
diff --git a/odoo/addons/base/tests/test_deprecation.py b/odoo/addons/base/tests/test_deprecation.py
index bb68d980c68..f1d7442827e 100644
--- a/odoo/addons/base/tests/test_deprecation.py
+++ b/odoo/addons/base/tests/test_deprecation.py
@@ -27,3 +27,12 @@ class TestModelDeprecations(TransactionCase):
if module:
msg += f" in {module}"
self.fail(msg)
+
+ def test_name_get(self):
+ for model_name, Model in self.registry.items():
+ with self.subTest(model=model_name):
+ # name_get should exist but define by BaseModel
+ module = inspect.getmodule(Model.name_get)
+ if module.__name__ == 'odoo.models':
+ continue
+ self.fail(f"Deprecated name_get method found on {model_name} in {module.__name__}, you should override `_compute_display_name` instead")
diff --git a/odoo/addons/base/tests/test_expression.py b/odoo/addons/base/tests/test_expression.py
index e4f651f0677..067674c0648 100644
--- a/odoo/addons/base/tests/test_expression.py
+++ b/odoo/addons/base/tests/test_expression.py
@@ -1127,7 +1127,7 @@ class TestQueries(TransactionCase):
)
)
)
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
Model.search(domain)
@@ -1139,7 +1139,7 @@ class TestQueries(TransactionCase):
SELECT "res_partner"."id"
FROM "res_partner"
WHERE (("res_partner"."active" = %s) AND ("res_partner"."name"::text LIKE %s))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
Model.search([('name', 'like', 'foo')])
@@ -1296,7 +1296,7 @@ class TestMany2one(TransactionCase):
SELECT "res_partner"."id"
FROM "res_partner"
WHERE ("res_partner"."company_id" = %s)
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('company_id', '=', self.company.id)])
@@ -1308,7 +1308,7 @@ class TestMany2one(TransactionCase):
FROM "res_company"
WHERE ("res_company"."name"::text LIKE %s)
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('company_id.name', 'like', self.company.name)])
@@ -1324,7 +1324,7 @@ class TestMany2one(TransactionCase):
WHERE ("res_partner"."name"::text LIKE %s)
))
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('company_id.partner_id.name', 'like', self.company.name)])
@@ -1340,7 +1340,7 @@ class TestMany2one(TransactionCase):
FROM "res_country"
WHERE ("res_country"."code"::text LIKE %s)
)))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([
'|',
@@ -1359,7 +1359,7 @@ class TestMany2one(TransactionCase):
FROM "res_company"
WHERE (("res_company"."active" = %s) AND ("res_company"."name"::text LIKE %s))
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
company_ids = self.company._search([('name', 'like', self.company.name)], order='id')
self.Partner.search([('company_id', 'in', company_ids)])
@@ -1375,7 +1375,7 @@ class TestMany2one(TransactionCase):
ORDER BY "res_company"."id"
LIMIT 1
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
company_ids = self.company._search([('name', 'like', self.company.name)], order='id', limit=1)
self.Partner.search([('company_id', 'in', company_ids)])
@@ -1390,7 +1390,7 @@ class TestMany2one(TransactionCase):
SELECT "res_partner"."id"
FROM "res_partner"
WHERE ("res_partner"."company_id" IN %s)
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
company_ids = self.company._search([('name', 'like', self.company.name)], order='id')
company_ids = tuple(company_ids)
@@ -1406,7 +1406,7 @@ class TestMany2one(TransactionCase):
SELECT "res_partner"."id"
FROM "res_partner"
WHERE ("res_partner"."company_id" IN %s)
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
companies = self.company.search([('name', 'like', self.company.name)], order='id')
company_ids = companies._as_query(ordered=False)
@@ -1424,7 +1424,7 @@ class TestMany2one(TransactionCase):
LEFT JOIN "res_company" AS "res_partner__company_id" ON
("res_partner"."company_id" = "res_partner__company_id"."id")
WHERE ("res_partner__company_id"."name"::text LIKE %s)
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('company_id.name', 'like', self.company.name)])
@@ -1438,7 +1438,7 @@ class TestMany2one(TransactionCase):
FROM "res_partner"
WHERE ("res_partner"."name"::text LIKE %s)
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('company_id.partner_id.name', 'like', self.company.name)])
@@ -1457,7 +1457,7 @@ class TestMany2one(TransactionCase):
("res_company"."partner_id" = "res_company__partner_id"."id")
WHERE ("res_company__partner_id"."name"::text LIKE %s)
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('company_id.partner_id.name', 'like', self.company.name)])
@@ -1474,7 +1474,7 @@ class TestMany2one(TransactionCase):
LEFT JOIN "res_partner" AS "res_partner__company_id__partner_id" ON
("res_partner__company_id"."partner_id" = "res_partner__company_id__partner_id"."id")
WHERE ("res_partner__company_id__partner_id"."name"::text LIKE %s)
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('company_id.partner_id.name', 'like', self.company.name)])
@@ -1496,7 +1496,7 @@ class TestMany2one(TransactionCase):
("res_partner"."company_id" = "res_partner__company_id"."id")
WHERE (("res_partner__company_id"."name"::text LIKE %s)
OR ("res_partner__country_id"."code"::text LIKE %s))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([
'|',
@@ -1515,7 +1515,7 @@ class TestMany2one(TransactionCase):
FROM "res_company"
WHERE ("res_company"."name"::text LIKE %s)
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('company_id', 'like', self.company.name)])
@@ -1527,7 +1527,7 @@ class TestMany2one(TransactionCase):
FROM "res_company"
WHERE (("res_company"."name"::text not like %s) OR "res_company"."name" IS NULL))
) OR "res_partner"."company_id" IS NULL)
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('company_id', 'not like', "blablabla")])
@@ -1556,7 +1556,7 @@ class TestOne2many(TransactionCase):
WHERE ("res_partner"."id" IN (
SELECT "partner_id" FROM "res_partner_bank" WHERE "id" IN %s
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('bank_ids', 'in', self.partner.bank_ids.ids)])
@@ -1568,7 +1568,7 @@ class TestOne2many(TransactionCase):
FROM "res_partner_bank"
WHERE ("res_partner_bank"."sanitized_acc_number"::text LIKE %s)
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('bank_ids.sanitized_acc_number', 'like', '12')])
@@ -1584,7 +1584,7 @@ class TestOne2many(TransactionCase):
WHERE ("res_partner_bank"."sanitized_acc_number"::text LIKE %s)
)) AND "res_partner"."parent_id" IS NOT NULL
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('child_ids.bank_ids.sanitized_acc_number', 'like', '12')])
@@ -1601,7 +1601,7 @@ class TestOne2many(TransactionCase):
WHERE ("res_partner"."id" IN (
SELECT "partner_id" FROM "res_partner_bank" WHERE "id" IN %s
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('bank_ids', 'in', self.partner.bank_ids.ids)])
@@ -1613,7 +1613,7 @@ class TestOne2many(TransactionCase):
FROM "res_partner_bank"
WHERE ("res_partner_bank"."sanitized_acc_number"::text LIKE %s)
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('bank_ids.sanitized_acc_number', 'like', '12')])
@@ -1629,7 +1629,7 @@ class TestOne2many(TransactionCase):
FROM "res_partner_bank"
WHERE ("res_partner_bank"."sanitized_acc_number"::text LIKE %s)
)))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([
('bank_ids.sanitized_acc_number', 'like', '12'),
@@ -1647,7 +1647,7 @@ class TestOne2many(TransactionCase):
FROM "res_partner_bank"
WHERE ("res_partner_bank"."sanitized_acc_number"::text LIKE %s)))
)))
- ORDER BY "res_partner"."display_name",
+ ORDER BY "res_partner"."complete_name",
"res_partner"."id"
''']):
self.Partner.search([('child_ids.bank_ids.sanitized_acc_number', 'like', '12')])
@@ -1678,7 +1678,7 @@ class TestOne2many(TransactionCase):
)
))
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('child_ids.bank_ids.id', 'in', self.partner.bank_ids.ids)])
@@ -1704,7 +1704,7 @@ class TestOne2many(TransactionCase):
"res_partner__state_id__country_id"."code"::text LIKE %s
))
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('child_ids.state_id.country_id.code', 'like', 'US')])
@@ -1719,7 +1719,7 @@ class TestOne2many(TransactionCase):
FROM "res_partner_bank"
WHERE ("res_partner_bank"."sanitized_acc_number"::text LIKE %s)
))
- ORDER BY "res_partner"."display_name", "res_partner"."id"
+ ORDER BY "res_partner"."complete_name", "res_partner"."id"
''']):
self.Partner.search([('bank_ids', 'like', '12')])
diff --git a/odoo/addons/base/tests/test_res_config.py b/odoo/addons/base/tests/test_res_config.py
index b0ad82ed070..4813a38cf0b 100644
--- a/odoo/addons/base/tests/test_res_config.py
+++ b/odoo/addons/base/tests/test_res_config.py
@@ -225,7 +225,7 @@ class TestResConfigExecute(TransactionCase):
settings.set_values()
# Check user has access to all models of relational fields in view
- # because the webclient makes a name_get request for all specified records
+ # because the webclient makes a read of display_name request for all specified records
# even if they are not shown to the user.
settings_view_arch = etree.fromstring(settings.get_view(view_id=self.settings_view.id)['arch'])
seen_fields = set()
diff --git a/odoo/addons/base/tests/test_res_partner.py b/odoo/addons/base/tests/test_res_partner.py
index 6ad7c7989f3..74972a2632f 100644
--- a/odoo/addons/base/tests/test_res_partner.py
+++ b/odoo/addons/base/tests/test_res_partner.py
@@ -27,21 +27,21 @@ class TestPartner(TransactionCase):
ns_res = self.env['res.partner'].with_user(public_user).sudo().name_search('Vlad', args=[('user_ids.email', 'ilike', 'vlad')])
self.assertEqual(set(i[0] for i in ns_res), set(test_user.partner_id.ids))
- def test_name_get(self):
- """ Check name_get on partner, especially with different context
- Check name_get correctly return name with context. """
+ def test_display_name(self):
+ """ Check display_name on partner, especially with different context
+ Check display_name correctly return name with context. """
test_partner_jetha = self.env['res.partner'].create({'name': 'Jethala', 'street': 'Powder gali', 'street2': 'Gokuldham Society'})
test_partner_bhide = self.env['res.partner'].create({'name': 'Atmaram Bhide'})
- res_jetha = test_partner_jetha.with_context(show_address=1).name_get()
- self.assertEqual(res_jetha[0][1], "Jethala\nPowder gali\nGokuldham Society", "name should contain comma separated name and address")
- res_bhide = test_partner_bhide.with_context(show_address=1).name_get()
- self.assertEqual(res_bhide[0][1], "Atmaram Bhide", "name should contain only name if address is not available, without extra commas")
+ res_jetha = test_partner_jetha.with_context(show_address=1).display_name
+ self.assertEqual(res_jetha, "Jethala\nPowder gali\nGokuldham Society", "name should contain comma separated name and address")
+ res_bhide = test_partner_bhide.with_context(show_address=1).display_name
+ self.assertEqual(res_bhide, "Atmaram Bhide", "name should contain only name if address is not available, without extra commas")
- res_jetha = test_partner_jetha.with_context(show_address=1, address_inline=1).name_get()
- self.assertEqual(res_jetha[0][1], "Jethala, Powder gali, Gokuldham Society", "name should contain comma separated name and address")
- res_bhide = test_partner_bhide.with_context(show_address=1, address_inline=1).name_get()
- self.assertEqual(res_bhide[0][1], "Atmaram Bhide", "name should contain only name if address is not available, without extra commas")
+ res_jetha = test_partner_jetha.with_context(show_address=1, address_inline=1).display_name
+ self.assertEqual(res_jetha, "Jethala, Powder gali, Gokuldham Society", "name should contain comma separated name and address")
+ res_bhide = test_partner_bhide.with_context(show_address=1, address_inline=1).display_name
+ self.assertEqual(res_bhide, "Atmaram Bhide", "name should contain only name if address is not available, without extra commas")
def test_company_change_propagation(self):
""" Check propagation of company_id across children """
@@ -182,8 +182,7 @@ class TestPartner(TransactionCase):
partner_merge_wizard = self.env['base.partner.merge.automatic.wizard'].with_context(
{'partner_show_db_id': True, 'default_dst_partner_id': test_partner}).new()
self.assertEqual(
- partner_merge_wizard.dst_partner_id.name_get(),
- [(test_partner.id, expected_partner_name)],
+ partner_merge_wizard.dst_partner_id.display_name, expected_partner_name,
"'Destination Contact' name should contain db ID in brackets"
)
diff --git a/odoo/addons/base/tests/test_translate.py b/odoo/addons/base/tests/test_translate.py
index beda9616116..e542a4116e9 100644
--- a/odoo/addons/base/tests/test_translate.py
+++ b/odoo/addons/base/tests/test_translate.py
@@ -368,7 +368,7 @@ class TestTranslation(TransactionCase):
def test_101_create_translated_record(self):
category = self.customers.with_context({})
- self.assertEqual(category.name, 'Customers', "Error in basic name_get")
+ self.assertEqual(category.name, 'Customers', "Error in basic name")
category_fr = category.with_context({'lang': 'fr_FR'})
self.assertEqual(category_fr.name, 'Clients', "Translation not found")
diff --git a/odoo/addons/base/views/res_partner_views.xml b/odoo/addons/base/views/res_partner_views.xml
index 5ede699ccf2..39487be4215 100644
--- a/odoo/addons/base/views/res_partner_views.xml
+++ b/odoo/addons/base/views/res_partner_views.xml
@@ -430,7 +430,7 @@
+ filter_domain="['|', '|', '|', '|', ('complete_name', 'ilike', self), ('ref', '=', self), ('email', 'ilike', self), ('vat', 'ilike', self), ('company_registry', 'ilike', self)]"/>
diff --git a/odoo/addons/test_access_rights/tests/test_check_access.py b/odoo/addons/test_access_rights/tests/test_check_access.py
index 7cf3d383e30..10b08ff72fa 100644
--- a/odoo/addons/test_access_rights/tests/test_check_access.py
+++ b/odoo/addons/test_access_rights/tests/test_check_access.py
@@ -51,8 +51,4 @@ class TestAccess(odoo.tests.HttpCase):
})
document = self.env['test_access_right.ticket'].with_user(no_access_user)
res = document.sudo().name_search('Need help here')
- #Invalide cache in case the name is already there
- #and will not trigget check_access_rights when
- #the name_get will access the name
- self.document.invalidate_model(['name'])
self.assertEqual(res[0][1], "Need help here")
diff --git a/odoo/addons/test_impex/models.py b/odoo/addons/test_impex/models.py
index d249460105b..136798c7bea 100644
--- a/odoo/addons/test_impex/models.py
+++ b/odoo/addons/test_impex/models.py
@@ -46,8 +46,9 @@ for name, field in MODELS:
const = fields.Integer(default=4)
value = field
- def name_get(self):
- return [(record.id, "%s:%s" % (self._name, record.value)) for record in self]
+ def _compute_display_name(self):
+ for record in self:
+ record.display_name = f"{self._name}:{record.value}"
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
@@ -59,7 +60,7 @@ for name, field in MODELS:
class One2ManyChild(models.Model):
_name = 'export.one2many.child'
_description = 'Export One to Many Child'
- # FIXME: orm.py:1161, fix to name_get on m2o field
+ # FIXME: orm.py:1161, fix to display_name on m2o field
_rec_name = 'value'
parent_id = fields.Many2one('export.one2many')
@@ -67,8 +68,9 @@ class One2ManyChild(models.Model):
m2o = fields.Many2one('export.integer')
value = fields.Integer()
- def name_get(self):
- return [(record.id, "%s:%s" % (self._name, record.value)) for record in self]
+ def _compute_display_name(self):
+ for record in self:
+ record.display_name = f"{self._name}:{record.value}"
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
@@ -91,7 +93,7 @@ class One2ManyMultiple(models.Model):
class One2ManyChildMultiple(models.Model):
_name = 'export.one2many.multiple.child'
- # FIXME: orm.py:1161, fix to name_get on m2o field
+ # FIXME: orm.py:1161, fix to display_name on m2o field
_rec_name = 'value'
_description = 'Export One To Many Multiple Child'
@@ -99,8 +101,9 @@ class One2ManyChildMultiple(models.Model):
str = fields.Char()
value = fields.Integer()
- def name_get(self):
- return [(record.id, "%s:%s" % (self._name, record.value)) for record in self]
+ def _compute_display_name(self):
+ for record in self:
+ record.display_name = f"{self._name}:{record.value}"
class One2ManyChild1(models.Model):
@@ -118,14 +121,15 @@ class One2ManyChild2(models.Model):
class Many2ManyChild(models.Model):
_name = 'export.many2many.other'
_description = 'Export Many to Many Other'
- # FIXME: orm.py:1161, fix to name_get on m2o field
+ # FIXME: orm.py:1161, fix to display_name on m2o field
_rec_name = 'value'
str = fields.Char()
value = fields.Integer()
- def name_get(self):
- return [(record.id, "%s:%s" % (self._name, record.value)) for record in self]
+ def _compute_display_name(self):
+ for record in self:
+ record.display_name = f"{self._name}:{record.value}"
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
diff --git a/odoo/addons/test_impex/tests/test_export.py b/odoo/addons/test_impex/tests/test_export.py
index cf10c68acca..0e3546b0265 100644
--- a/odoo/addons/test_impex/tests/test_export.py
+++ b/odoo/addons/test_impex/tests/test_export.py
@@ -257,7 +257,7 @@ class test_datetime(CreatorCase):
def test_tz(self):
""" Export converts the value in the user's TZ
- .. note:: on the other hand, export uses user lang for name_get
+ .. note:: on the other hand, export uses user lang for display_name
"""
self.assertEqual(
self.export('2011-11-07 21:05:48', context={'tz': 'Pacific/Norfolk'}),
@@ -326,13 +326,12 @@ class test_m2o(CreatorCase):
[['']])
def test_basic(self):
- """ Exported value is the name_get of the related object
+ """ Exported value is the display_name of the related object
"""
record = self.env['export.integer'].create({'value': 42})
- name = dict(record.name_get())[record.id]
self.assertEqual(
self.export(record.id),
- [[name]])
+ [[record.display_name]])
def test_path(self):
""" Can recursively export fields of m2o via path
@@ -389,7 +388,7 @@ class test_o2m(CreatorCase):
def test_single(self):
self.assertEqual(
self.export([Command.create({'value': 42})]),
- # name_get result
+ # display_name result
[[u'export.one2many.child:42']])
def test_single_subfield(self):
@@ -600,7 +599,7 @@ class test_m2m(CreatorCase):
def test_single(self):
self.assertEqual(
self.export([Command.create({'value': 42})]),
- # name_get result
+ # display_name result
[[u'export.many2many.other:42']])
def test_single_subfield(self):
diff --git a/odoo/addons/test_impex/tests/test_load.py b/odoo/addons/test_impex/tests/test_load.py
index 2a6b506c47d..69e57929594 100644
--- a/odoo/addons/test_impex/tests/test_load.py
+++ b/odoo/addons/test_impex/tests/test_load.py
@@ -68,7 +68,7 @@ class ImporterCase(common.TransactionCase):
return d['name']
name = record.display_name
- # fix dotted name_get results, otherwise xid lookups blow up
+ # fix dotted display_name results, otherwise xid lookups blow up
name = name.replace('.', '-')
ModelData.create({
'name': name,
@@ -562,14 +562,11 @@ class test_m2o(ImporterCase):
# create integer objects
record1 = self.env['export.integer'].create({'value': 42})
record2 = self.env['export.integer'].create({'value': 36})
- # get its name
- name1 = dict(record1.name_get())[record1.id]
- name2 = dict(record2.name_get())[record2.id]
# preheat the oven
for _ in range(5):
with contextlib.closing(self.env.cr.savepoint(flush=False)):
- self.import_(['value'], [[name1], [name1], [name2]])
+ self.import_(['value'], [[record1.display_name], [record1.display_name], [record2.display_name]])
# 1 x SAVEPOINT load
# 3 x name_search
@@ -580,19 +577,19 @@ class test_m2o(ImporterCase):
# => 10
with self.assertQueryCount(8):
result = self.import_(['value'], [
- # import by name_get
- [name1],
- [name1],
- [name2],
+ # import by display_name
+ [record1.display_name],
+ [record1.display_name],
+ [record2.display_name],
])
self.assertFalse(result['messages'])
self.assertEqual(len(result['ids']), 3)
# correct ids assigned to corresponding records
self.assertEqual([
- (record1.id, name1),
- (record1.id, name1),
- (record2.id, name2),],
+ (record1.id, record1.display_name),
+ (record1.id, record1.display_name),
+ (record2.id, record2.display_name),],
values(self.read()))
def test_by_xid(self):
@@ -616,19 +613,17 @@ class test_m2o(ImporterCase):
def test_by_names(self):
record1 = self.env['export.integer'].create({'value': 42})
record2 = self.env['export.integer'].create({'value': 42})
- name1 = dict(record1.name_get())[record1.id]
- name2 = dict(record2.name_get())[record2.id]
# names should be the same
- self.assertEqual(name1, name2)
+ self.assertEqual(record1.display_name, record2.display_name)
- result = self.import_(['value'], [[name2]])
+ result = self.import_(['value'], [[record2.display_name]])
self.assertEqual(
result['messages'],
[message(u"Found multiple matches for value 'export.integer:42' in field 'Value' (2 matches)",
type='warning')])
self.assertEqual(len(result['ids']), 1)
self.assertEqual([
- (record1.id, name1)
+ (record1.id, record1.display_name)
], values(self.read()))
def test_fail_by_implicit_id(self):
@@ -859,7 +854,7 @@ class test_m2m(ImporterCase):
class test_o2m(ImporterCase):
model_name = 'export.one2many'
- def test_name_get(self):
+ def test_display_name(self):
s = u'Java is a DSL for taking large XML files and converting them ' \
u'to stack traces'
result = self.import_(
diff --git a/odoo/addons/test_new_api/models/test_unity_read.py b/odoo/addons/test_new_api/models/test_unity_read.py
index 8d5939ea5a2..0c827138511 100644
--- a/odoo/addons/test_new_api/models/test_unity_read.py
+++ b/odoo/addons/test_new_api/models/test_unity_read.py
@@ -43,15 +43,14 @@ class Person(models.Model):
lesson_ids = fields.Many2many('test_new_api.lesson', 'course_id')
employer_id = fields.Many2one('test_new_api.employer')
- def name_get(self):
+ def _compute_display_name(self):
"""
use to check that a context has can still have an impact when reading the names of a many2one
"""
- return [(record.id,
- ("particular " if 'particular' in self.env.context else "") +
- record.name +
- (" special" if 'special' in self.env.context else ""))
- for record in self]
+ particular = "particular " if 'particular' in self.env.context else ""
+ special = " special" if 'special' in self.env.context else ""
+ for record in self:
+ record.display_name = f"{particular}{record.name}{special}"
class Employer(models.Model):
_name = 'test_new_api.employer'
diff --git a/odoo/addons/test_new_api/tests/test_onchange.py b/odoo/addons/test_new_api/tests/test_onchange.py
index 16ee6372441..62321733efd 100644
--- a/odoo/addons/test_new_api/tests/test_onchange.py
+++ b/odoo/addons/test_new_api/tests/test_onchange.py
@@ -106,7 +106,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
self.env.invalidate_all()
result = Category.onchange(values, 'parent', field_onchange).get('value', {})
self.assertIn('root_categ', result)
- self.assertEqual(result['root_categ'], root.name_get()[0])
+ self.assertEqual(result['root_categ'], (root.id, root.display_name))
values.update(result)
values['parent'] = False
@@ -160,21 +160,21 @@ class TestOnChange(SavepointCaseWithUserDemo):
Command.update(message1.id, {
'name': "[%s] %s" % ("Foo", USER.name),
'body': "ABC",
- 'author': USER.name_get()[0],
+ 'author': (USER.id, USER.display_name),
'size': 3,
'important': False,
}),
Command.update(message2.id, {
'name': "[%s] %s" % ("Foo", USER.name),
'body': "XYZ", # this must be sent back
- 'author': USER.name_get()[0],
+ 'author': (USER.id, USER.display_name),
'size': 3,
'important': False,
}),
Command.create({
'name': "[%s] %s" % ("Foo", USER.name),
'body': "ABC",
- 'author': USER.name_get()[0],
+ 'author': (USER.id, USER.display_name),
'size': 3,
'important': False,
}),
@@ -231,7 +231,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
(0, REFERENCE, {
'name': "[%s] %s" % ("Foo", USER.name),
'body': BODY,
- 'author': USER.name_get()[0],
+ 'author': (USER.id, USER.display_name),
'size': len(BODY),
'important': False,
}),
@@ -479,7 +479,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
[Command.clear(), Command.update(email.id, {
'name': u'[Foo Bar] %s' % USER.name,
'body': BODY,
- 'author': USER.name_get()[0],
+ 'author': (USER.id, USER.display_name),
'size': len(BODY),
'important': True,
'email_to': demo.email,
@@ -500,7 +500,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
onchange_result = {
'message_name': 'Hey dude!',
- 'message_currency': self.env.user.name_get()[0],
+ 'message_currency': (self.env.user.id, self.env.user.display_name),
}
self.env.invalidate_all()
@@ -625,7 +625,6 @@ class TestOnChange(SavepointCaseWithUserDemo):
record = form.save()
self.assertEqual(record.name, False)
self.assertEqual(record.display_name, "")
- self.assertEqual(record.name_get(), [(record.id, "")])
class TestComputeOnchange(common.TransactionCase):
diff --git a/odoo/addons/test_new_api/tests/test_onchange2.py b/odoo/addons/test_new_api/tests/test_onchange2.py
index 9f020a87078..7509823eb7f 100644
--- a/odoo/addons/test_new_api/tests/test_onchange2.py
+++ b/odoo/addons/test_new_api/tests/test_onchange2.py
@@ -705,7 +705,6 @@ class TestOnchange2(SavepointCaseWithUserDemo):
record = form.save()
self.assertEqual(record.name, False)
self.assertEqual(record.display_name, "")
- self.assertEqual(record.name_get(), [(record.id, "")])
def test_reading_one2many_and_inverse_is_not_supported(self):
# when reading a relation one2many, sometime the relation itself defines
@@ -759,7 +758,6 @@ class TestOnchange2(SavepointCaseWithUserDemo):
'root_categ': {'id': root.id, 'display_name': root.name, 'color': root.color},
})
- @skip("read() on many2one fields currently use name_get() instead of field 'display_name'")
def test_one2many_field_with_context_many2one(self):
""" test many2one fields with a context on their one2many container field """
multi = self.env['test_new_api.multi'].create({})
@@ -791,8 +789,8 @@ class TestOnchange2(SavepointCaseWithUserDemo):
'name': 'A partner',
'email': 'foo@example.com',
})
- display_name = partner.name_get()[0][1]
- display_name_email = partner.with_context(show_email=True).name_get()[0][1]
+ display_name = partner.display_name
+ display_name_email = partner.with_context(show_email=True).display_name
self.assertNotEqual(display_name_email, display_name)
# modify 'partner'
diff --git a/odoo/addons/test_new_api/tests/test_properties.py b/odoo/addons/test_new_api/tests/test_properties.py
index 0b7ccd75a38..525af4240fd 100644
--- a/odoo/addons/test_new_api/tests/test_properties.py
+++ b/odoo/addons/test_new_api/tests/test_properties.py
@@ -524,12 +524,12 @@ class PropertiesCase(TestPropertiesMixin):
msg='When reading many2one default, it should return the display name',
)
- # read the default many2one and deactivate the name_get
+ # read the default many2one and deactivate the display_name
read_values = self.discussion_1.read(['attributes_definition'], load=None)[0]['attributes_definition']
self.assertEqual(
read_values[0]['default'],
self.partner.id,
- msg='If the name_get is deactivate, it should not return the display name',
+ msg='If the display_name is deactivate, it should not return the display name',
)
message = self.env['test_new_api.message'].create({
@@ -609,7 +609,7 @@ class PropertiesCase(TestPropertiesMixin):
In comparison with a simple "record.properties", the read method should not
record a recordset for the many2one, but a tuple with the record id and
- the record name_get.
+ the record display_name.
"""
properties_values = (self.message_1 | self.message_3).read(['attributes'])
@@ -646,13 +646,13 @@ class PropertiesCase(TestPropertiesMixin):
msg='Definition must be present when reading child')
self.assertEqual(many2one_property['value'], (self.partner.id, self.partner.display_name))
- # disable the name_get
+ # disable the display_name
properties_values = (self.message_1 | self.message_3).read(['attributes'], load=None)
many2one_property = properties_values[0]['attributes'][1]
self.assertEqual(
many2one_property['value'], self.partner.id,
- msg='If name_get is disable, should only return the record id')
+ msg='If display_name is disable, should only return the record id')
def test_properties_field_many2one_basic(self):
"""Test the basic (read, write...) of the many2one property."""
@@ -698,7 +698,7 @@ class PropertiesCase(TestPropertiesMixin):
with self.assertQueryCount(4):
# 1 query to read the field
# 1 query to read the definition
- # 2 queries to check if the many2one still exists / name_get
+ # 2 queries to check if the many2one still exists / display_name
self.assertFalse(self.message_2.read(['attributes'])[0]['attributes'][0]['value'])
# remove the partner, and use the read method
@@ -1072,7 +1072,7 @@ class PropertiesCase(TestPropertiesMixin):
"string": "Partners",
"type": "many2many",
"comodel": "test_new_api.partner",
- "value": partners[:10].name_get(),
+ "value": list(zip(partners[:10]._ids, partners[:10].mapped('display_name'))),
}
]
attributes = self.message_1.read(['attributes'], load=None)[0]['attributes']
@@ -1086,7 +1086,7 @@ class PropertiesCase(TestPropertiesMixin):
partners[5].unlink()
with self.assertQueryCount(5):
properties = self.message_1.read(['attributes'])[0]['attributes']
- self.assertEqual(properties[0]['value'], partners[6:10].name_get())
+ self.assertEqual(properties[0]['value'], list(zip(partners[6:10]._ids, partners[6:10].mapped('display_name'))))
# need to wait next write to clean data in database
# a single read won't clean the removed many2many
@@ -1097,7 +1097,7 @@ class PropertiesCase(TestPropertiesMixin):
sql_values = self._get_sql_properties(self.message_1)
self.assertEqual(sql_values, {'moderator_partner_ids': partners[6:10].ids})
- # read and disable name_get
+ # read and disable display_name
properties = self.message_1.read(['attributes'], load=None)[0]['attributes']
self.assertEqual(
properties[0]['value'],
diff --git a/odoo/addons/test_performance/tests/test_performance.py b/odoo/addons/test_performance/tests/test_performance.py
index b2bf41ac164..f15ff2bb85b 100644
--- a/odoo/addons/test_performance/tests/test_performance.py
+++ b/odoo/addons/test_performance/tests/test_performance.py
@@ -614,7 +614,7 @@ class TestPerformance(SavepointCaseWithUserDemo):
} for partner in partners]
@users('__system__', 'demo')
- def test_read_group_with_name_get(self):
+ def test_read_group_with_display_name(self):
model = self.env['test_performance.base']
expected = self.expected_read_group()
# use read_group and check the expected result
diff --git a/odoo/addons/test_read_group/tests/test_private_read_group.py b/odoo/addons/test_read_group/tests/test_private_read_group.py
index 09b223d8e77..1dd73ff40c5 100644
--- a/odoo/addons/test_read_group/tests/test_private_read_group.py
+++ b/odoo/addons/test_read_group/tests/test_private_read_group.py
@@ -46,10 +46,10 @@ class TestPrivateReadGroup(common.TransactionCase):
ON ("test_read_group_aggregate"."partner_id" = "test_read_group_aggregate__partner_id"."id")
GROUP BY "test_read_group_aggregate"."key",
"test_read_group_aggregate"."partner_id",
- "test_read_group_aggregate__partner_id"."display_name",
+ "test_read_group_aggregate__partner_id"."complete_name",
"test_read_group_aggregate__partner_id"."id"
ORDER BY "test_read_group_aggregate"."key" ASC,
- "test_read_group_aggregate__partner_id"."display_name",
+ "test_read_group_aggregate__partner_id"."complete_name",
"test_read_group_aggregate__partner_id"."id"
"""]):
self.assertEqual(
@@ -152,9 +152,9 @@ class TestPrivateReadGroup(common.TransactionCase):
ON ("test_read_group_aggregate"."partner_id" = "test_read_group_aggregate__partner_id"."id")
GROUP BY "test_read_group_aggregate"."display_name",
"test_read_group_aggregate"."partner_id",
- "test_read_group_aggregate__partner_id"."display_name",
+ "test_read_group_aggregate__partner_id"."complete_name",
"test_read_group_aggregate__partner_id"."id"
- ORDER BY "test_read_group_aggregate__partner_id"."display_name" DESC,
+ ORDER BY "test_read_group_aggregate__partner_id"."complete_name" DESC,
"test_read_group_aggregate__partner_id"."id" DESC
"""]):
result = Model._read_group(
diff --git a/odoo/fields.py b/odoo/fields.py
index 91f9f828f07..a228ce66f3f 100644
--- a/odoo/fields.py
+++ b/odoo/fields.py
@@ -941,14 +941,14 @@ class Field(MetaField('DummyField', (object,), {})):
convert = self.convert_to_record
return [convert(value, record) for value, record in zip(values, records)]
- def convert_to_read(self, value, record, use_name_get=True):
+ def convert_to_read(self, value, record, use_display_name=True):
""" Convert ``value`` from the record format to the format returned by
method :meth:`BaseModel.read`.
:param value:
:param record:
- :param bool use_name_get: when True, the value's display name will be
- computed using :meth:`BaseModel.name_get`, if relevant for the field
+ :param bool use_display_name: when True, the value's display name will be
+ computed using `display_name`, if relevant for the field
"""
return False if value is None else value
@@ -1441,7 +1441,7 @@ class Integer(Field):
def convert_to_record(self, value, record):
return value or 0
- def convert_to_read(self, value, record, use_name_get=True):
+ def convert_to_read(self, value, record, use_display_name=True):
# Integer values greater than 2^31-1 are not supported in pure XMLRPC,
# so we have to pass them as floats :-(
if value and value > MAXINT:
@@ -1642,7 +1642,7 @@ class Monetary(Field):
def convert_to_record(self, value, record):
return value or 0.0
- def convert_to_read(self, value, record, use_name_get=True):
+ def convert_to_read(self, value, record, use_display_name=True):
return value
def convert_to_write(self, value, record):
@@ -2028,8 +2028,8 @@ class Html(_String):
r = r.decode()
return r and Markup(r)
- def convert_to_read(self, value, record, use_name_get=True):
- r = super().convert_to_read(value, record, use_name_get)
+ def convert_to_read(self, value, record, use_display_name=True):
+ r = super().convert_to_read(value, record, use_display_name)
if isinstance(r, bytes):
r = r.decode()
return r and Markup(r)
@@ -2778,7 +2778,7 @@ class Reference(Selection):
return record.env[res_model].browse(int(res_id))
return None
- def convert_to_read(self, value, record, use_name_get=True):
+ def convert_to_read(self, value, record, use_display_name=True):
return "%s,%s" % (value._name, value.id) if value else False
def convert_to_export(self, value, record):
@@ -2993,9 +2993,9 @@ class Many2one(_Relational):
ids = tuple(unique(id_ for id_ in values if id_ is not None))
return records.pool[self.comodel_name](records.env, ids, prefetch_ids)
- def convert_to_read(self, value, record, use_name_get=True):
- if use_name_get and value:
- # evaluate name_get() as superuser, because the visibility of a
+ def convert_to_read(self, value, record, use_display_name=True):
+ if use_display_name and value:
+ # evaluate display_name as superuser, because the visibility of a
# many2one field value (id and name) depends on the current record's
# access rights, and not the value's access rights.
try:
@@ -3304,10 +3304,10 @@ class Properties(Field):
# 'value': [1337, 'Bob'],
# }]
#
- def convert_to_read(self, value, record, use_name_get=True):
- return self.convert_to_read_multi([value], record, use_name_get)[0]
+ def convert_to_read(self, value, record, use_display_name=True):
+ return self.convert_to_read_multi([value], record, use_display_name)[0]
- def convert_to_read_multi(self, values, records, use_name_get=True):
+ def convert_to_read_multi(self, values, records, use_display_name=True):
if not records:
return values
assert len(values) == len(records)
@@ -3322,13 +3322,13 @@ class Properties(Field):
assert isinstance(value, dict), f"Wrong type {value!r}"
result.append(self._dict_to_list(value, definition))
- res_ids_per_model = self._get_res_ids_per_model(records, result, use_name_get)
+ res_ids_per_model = self._get_res_ids_per_model(records, result, use_display_name)
# value is in record format
for value in result:
self._parse_json_types(value, records.env, res_ids_per_model)
- if use_name_get:
+ if use_display_name:
for value in result:
self._add_display_name(value, records.env)
@@ -3353,7 +3353,7 @@ class Properties(Field):
record._cache[self.definition_record] = snapshot[self.definition_record].id or None
return super().convert_to_onchange(value, record, names)
- def _get_res_ids_per_model(self, records, values_list, use_name_get=True):
+ def _get_res_ids_per_model(self, records, values_list, use_display_name=True):
"""Read everything needed in batch for the given records.
To retrieve relational properties names, or to check their existence,
@@ -3390,7 +3390,7 @@ class Properties(Field):
recs = records.env[model].browse(ids).exists()
res_ids_per_model[model] = set(recs.ids)
- if use_name_get:
+ if use_display_name:
for record in recs:
# read a field to pre-fetch the recordset
try:
@@ -3511,7 +3511,7 @@ class Properties(Field):
@classmethod
def _add_display_name(cls, values_list, env, value_keys=('value', 'default')):
- """Add the "name_get" for each many2one / many2many properties.
+ """Add the "display_name" for each many2one / many2many properties.
Modify in place "values_list".
@@ -3760,7 +3760,7 @@ class PropertiesDefinition(Field):
This method accepts a list properties definition.
The relational properties (many2one / many2many) default value
- might contain the name_get of those records (and will be removed).
+ might contain the display_name of those records (and will be removed).
[{
'name': '3adf37f3258cfe40',
@@ -3865,12 +3865,12 @@ class PropertiesDefinition(Field):
return result
- def convert_to_read(self, value, record, use_name_get=True):
+ def convert_to_read(self, value, record, use_display_name=True):
# record format -> read format (list of dicts with display names)
if not value:
return value
- if use_name_get:
+ if use_display_name:
Properties._add_display_name(value, record.env, value_keys=('default',))
return value
@@ -4146,7 +4146,7 @@ class _RelationalMulti(_Relational):
corecords = corecords.filtered(Comodel._active_name).with_prefetch(prefetch_ids)
return corecords
- def convert_to_read(self, value, record, use_name_get=True):
+ def convert_to_read(self, value, record, use_display_name=True):
return value.ids
def convert_to_write(self, value, record):
@@ -4191,7 +4191,7 @@ class _RelationalMulti(_Relational):
raise ValueError("Wrong value for %s: %s" % (self, value))
def convert_to_export(self, value, record):
- return ','.join(name for id, name in value.name_get()) if value else ''
+ return ','.join(value.mapped('display_name')) if value else ''
def convert_to_display_name(self, value, record):
raise NotImplementedError()
diff --git a/odoo/models.py b/odoo/models.py
index 23d4bbef4dc..71b30d62e92 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -1039,7 +1039,7 @@ class BaseModel(metaclass=MetaModel):
break
if index is None:
# not found anything, assume we just want the
- # name_get in the first column
+ # display_name in the first column
name = None
index = i
@@ -1279,7 +1279,7 @@ class BaseModel(metaclass=MetaModel):
The following sub-fields may be set on the record (by key):
- * None is the name_get for the record (to use with name_create/name_search)
+ * None is the display_name for the record (to use with name_create/name_search)
* "id" is the External ID for the record
* ".id" is the Database ID for the record
"""
@@ -1323,7 +1323,7 @@ class BaseModel(metaclass=MetaModel):
comodel = self.env[fields[relfield].comodel_name]
# get only cells for this sub-field, should be strictly
- # non-empty, field path [None] is for name_get field
+ # non-empty, field path [None] is for display_name field
indices, subfields = zip(*((index, fnames[1:] or [None])
for index, fnames in enumerate(fields_)
if fnames[0] == relfield))
@@ -1604,18 +1604,18 @@ class BaseModel(metaclass=MetaModel):
def _compute_display_name(self):
"""Compute the value of the `display_name` field.
- In general `display_name` is equal to calling `name_get()[0][1]`.
-
- In that case, it is recommended to use `display_name` to uniformize the
- code and to potentially take advantage of prefetch when applicable.
-
- However some models might override this method. For them, the behavior
- might differ, and it is important to select which of `display_name` or
- `name_get()[0][1]` to call depending on the desired result.
+ The `display_name` field is a textual representation of the record.
+ This method can be overridden to change the representation. If needed,
+ it can be made field-dependent using :attr:`~odoo.api.depends` and
+ context-dependent using :attr:`~odoo.api.depends_context`.
"""
- names = dict(self.name_get())
- for record in self:
- record.display_name = names.get(record.id)
+ if self._rec_name:
+ convert = self._fields[self._rec_name].convert_to_display_name
+ for record in self:
+ record.display_name = convert(record[self._rec_name], record)
+ else:
+ for record in self:
+ record.display_name = f"{record._name},{record.id}"
def name_get(self):
"""Returns a textual representation for the records in ``self``, with
@@ -1628,20 +1628,14 @@ class BaseModel(metaclass=MetaModel):
:attr:`~.display_name` it is important that it resets to the
"default" behaviour if the context keys are empty / missing.
+ .. deprecated:: 17.0
+ Deprecated method, read([`display_name`]) instead
+
:return: list of pairs ``(id, text_repr)`` for each record
:rtype: list[(int, str)]
"""
- result = []
- name = self._rec_name
- if name in self._fields:
- convert = self._fields[name].convert_to_display_name
- for record in self:
- result.append((record.id, convert(record[name], record) or ""))
- else:
- for record in self:
- result.append((record.id, "%s,%s" % (record._name, record.id)))
-
- return result
+ warnings.warn("Since 17.0, deprecated method, read display_name instead", DeprecationWarning, 2)
+ return [(record.id, record.display_name) for record in self]
@api.model
def name_create(self, name):
@@ -1656,11 +1650,11 @@ class BaseModel(metaclass=MetaModel):
:param name: display name of the record to create
:rtype: tuple
- :return: the :meth:`~.name_get` pair value of the created record
+ :return: the (id, display_name) pair value of the created record
"""
if self._rec_name:
record = self.create({self._rec_name: name})
- return record.name_get()[0]
+ return record.id, record.display_name
else:
_logger.warning("Cannot execute name_create, no _rec_name defined on %s", self._name)
return False
@@ -1675,11 +1669,11 @@ class BaseModel(metaclass=MetaModel):
This is used for example to provide suggestions based on a partial
value for a relational field. Should usually behave as the reverse of
- :meth:`~.name_get`, but that is ont guaranteed.
+ ``display_name``, but that is not guaranteed.
This method is equivalent to calling :meth:`~.search` with a search
- domain based on ``display_name`` and then :meth:`~.name_get` on the
- result of the search.
+ domain based on ``display_name`` and mapping id and display_name on
+ the resulting search.
:param str name: the name pattern to match
:param list args: optional search domain (see :meth:`~.search` for
@@ -1691,7 +1685,7 @@ class BaseModel(metaclass=MetaModel):
:return: list of pairs ``(id, text_repr)`` for all matching records.
"""
ids = self._name_search(name, args, operator, limit=limit, order=self._order)
- return self.browse(ids).sudo().name_get()
+ return [(record.id, record.display_name) for record in self.browse(ids).sudo()]
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
@@ -2376,12 +2370,7 @@ class BaseModel(metaclass=MetaModel):
field_name = group.split(':')[0]
field = self._fields[field_name]
- if field.type in ('many2one', 'many2many') or field_name == 'id':
- ids = [row[group].id for row in rows_dict if row[group] and isinstance(row[group], BaseModel)]
- m2x_records = self.env[field.comodel_name].browse(ids)
- name_get_dict = dict(m2x_records.sudo().name_get())
-
- elif field.type in ('date', 'datetime'):
+ if field.type in ('date', 'datetime'):
locale = get_lang(self.env).code
fmt = DEFAULT_SERVER_DATETIME_FORMAT if field.type == 'datetime' else DEFAULT_SERVER_DATE_FORMAT
granularity = group.split(':')[1] if ':' in group else 'month'
@@ -2391,8 +2380,8 @@ class BaseModel(metaclass=MetaModel):
value = row[group]
if field.type in ('many2one', 'many2many') and isinstance(value, BaseModel):
+ row[group] = (value.id, value.sudo().display_name) if value else False
value = value.id
- row[group] = (value, name_get_dict[value]) if value else value
additional_domain = [(field_name, '=', value)]
@@ -3161,7 +3150,7 @@ class BaseModel(metaclass=MetaModel):
:param list fields: field names to return (default is all fields)
:param str load: loading mode, currently the only option is to set to
- ``None`` to avoid loading the ``name_get`` of m2o fields
+ ``None`` to avoid loading the `display_name` of m2o fields
:return: a list of dictionaries mapping field names to their values,
with one dictionary per record
:rtype: list
@@ -3337,7 +3326,7 @@ class BaseModel(metaclass=MetaModel):
values from the cache without doing a query when it is avoidable.
"""
data = [(record, {'id': record._ids[0]}) for record in self]
- use_name_get = (load == '_classic_read')
+ use_display_name = (load == '_classic_read')
for name in fnames:
field = self._fields[name]
if field.type == 'properties':
@@ -3350,7 +3339,7 @@ class BaseModel(metaclass=MetaModel):
except MissingError:
vals.clear()
- results = field.convert_to_read_multi(values_list, self.browse(records), use_name_get)
+ results = field.convert_to_read_multi(values_list, self.browse(records), use_display_name)
for record_read_vals, convert_result in zip(data, results):
record_read_vals[1][name] = convert_result
continue
@@ -3361,7 +3350,7 @@ class BaseModel(metaclass=MetaModel):
if not vals:
continue
try:
- vals[name] = convert(record[name], record, use_name_get)
+ vals[name] = convert(record[name], record, use_display_name)
except MissingError:
vals.clear()
result = [vals for record, vals in data if vals]
@@ -5260,7 +5249,7 @@ class BaseModel(metaclass=MetaModel):
Defaults to no sort.
:param read_kwargs: All read keywords arguments used to call
``read(..., **read_kwargs)`` method e.g. you can use
- ``search_read(..., load='')`` in order to avoid computing name_get
+ ``search_read(..., load='')`` in order to avoid computing display_name
:return: List of dictionaries containing the asked fields.
:rtype: list(dict).
"""
@@ -7018,13 +7007,6 @@ PGERROR_TO_OE = defaultdict(
'23514': convert_pgerror_constraint,
})
-
-def lazy_name_get(self):
- """ Evaluate self.name_get() lazily. """
- names = tools.lazy(lambda: dict(self.name_get()))
- return [(rid, tools.lazy(operator.getitem, names, rid)) for rid in self.ids]
-
-
# keep those imports here to avoid dependency cycle errors
# pylint: disable=wrong-import-position
from . import fields