Skip to content

Commit

Permalink
[REM] core: remove name_get API
Browse files Browse the repository at this point in the history
Rational
========

Since v8, the `display_name` field is present on all models. By default,
`display_name` uses `name_get` which has pretty much the same purpose
(return record name used by the web client). Gradually, many (backend)
developers (and the ORM: 6da1c3a)
started using `display_name` (more convenient than
`record.name_get()[0][1]`) but it still had the `name_get` override.
It becomes more complex than necessary and poeple start to misunderstand
the two (and sometimes override both, leading to inconstiencies between
`display_name`/`name_get`).

To simplify the ORM and the API, we decided to keep only one of them,
the `display_name` field:
- It is much more convenient from a backend point of view
(`record.name_get()[0][1]` vs `record.display_name`)
- It is cached during the same transaction (and invalidated if
its dependencies change)
- It can be overridden like any other compute field (override
`_compute_display_name` with any extra dependencies)
- `name_get` is replaced by `read(['display_name'])`
(API perceptive), which can actually be more efficient
(if `display_name`'s depends are correct, the ORM will only fetch the
fields it needs instead of every prefetchable field)

Changes
=======

- Deprecates `name_get` for the v17 and based the method on
`display_name` (the opposite of before)
- Converts all usage of `name_get`
- Overrides of `name_get` are now overrides of `_compute_display_name`
- For `res.partner`, rename the field store `display_name` into
`complete_name` because `display_name` context-dependent and it makes
no sense to have a compute store that is context-dependent.
- Previously, it was possible to return multiple names for the same
record with `name_get`, but it was tricky and most of the usage of
this `name_get` didn't take this into account. The only example of
this is the `name_get` of `product.product`
(now use `", ".join(<names>)`).

odoo/enterprise#42599
odoo/upgrade#4780
odoo/documentation#4639
  • Loading branch information
ryv-odoo committed Jun 19, 2023
1 parent e1f1767 commit 24a617b
Show file tree
Hide file tree
Showing 169 changed files with 787 additions and 1,249 deletions.
17 changes: 7 additions & 10 deletions addons/account/models/account_account.py
Expand Up @@ -597,12 +597,9 @@ def _onchange_name(self):
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):
Expand Down Expand Up @@ -701,7 +698,8 @@ def name_create(self, name):
"""
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
Expand Down Expand Up @@ -828,15 +826,14 @@ def _compute_code_prefix_start(self):
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):
Expand Down
9 changes: 3 additions & 6 deletions addons/account/models/account_account_tag.py
Expand Up @@ -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):
Expand Down
6 changes: 3 additions & 3 deletions addons/account/models/account_incoterms.py
Expand Up @@ -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)
8 changes: 3 additions & 5 deletions addons/account/models/account_journal.py
Expand Up @@ -696,14 +696,12 @@ def set_bank_account(self, acc_number, bank_id=None):
'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,
Expand Down
6 changes: 2 additions & 4 deletions addons/account/models/account_move.py
Expand Up @@ -2366,11 +2366,9 @@ def unlink(self):
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'):
Expand Down
17 changes: 9 additions & 8 deletions addons/account/models/account_move_line.py
Expand Up @@ -1522,14 +1522,15 @@ def unlink(self):

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)
Expand Down
5 changes: 3 additions & 2 deletions addons/account/models/account_payment.py
Expand Up @@ -740,8 +740,9 @@ def unlink(self):
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
Expand Down
9 changes: 5 additions & 4 deletions addons/account/models/account_payment_method.py
Expand Up @@ -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):
Expand Down
12 changes: 6 additions & 6 deletions addons/account/models/account_report.py
Expand Up @@ -204,11 +204,9 @@ def _get_copied_name(self):
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):
Expand Down Expand Up @@ -562,8 +560,10 @@ def _unlink_archive_used_tags(self):
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"""
Expand Down
6 changes: 2 additions & 4 deletions addons/account/models/account_tax.py
Expand Up @@ -362,8 +362,7 @@ def copy(self, default=None):
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:
Expand All @@ -372,8 +371,7 @@ def name_get(self):
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):
Expand Down
12 changes: 5 additions & 7 deletions addons/account/models/res_partner_bank.py
Expand Up @@ -307,15 +307,13 @@ def unlink(self):
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
6 changes: 2 additions & 4 deletions addons/analytic/models/analytic_account.py
Expand Up @@ -115,16 +115,14 @@ def _check_company_consistency(self):
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 {})
Expand Down
8 changes: 3 additions & 5 deletions addons/base_address_extended/models/res_city.py
Expand Up @@ -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
9 changes: 3 additions & 6 deletions addons/calendar/models/calendar_event.py
Expand Up @@ -645,7 +645,7 @@ def write(self, values):

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(
Expand All @@ -654,11 +654,8 @@ def name_get(self):
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):
Expand Down
10 changes: 6 additions & 4 deletions addons/crm_iap_mine/models/crm_iap_lead_role.py
Expand Up @@ -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):
Expand All @@ -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()
5 changes: 3 additions & 2 deletions addons/crm_iap_mine/models/crm_iap_lead_seniority.py
Expand Up @@ -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()
8 changes: 3 additions & 5 deletions addons/event/models/event_event.py
Expand Up @@ -589,11 +589,10 @@ def write(self, vals):
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:
Expand All @@ -606,8 +605,7 @@ def name_get(self):
)
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):
Expand Down
7 changes: 4 additions & 3 deletions addons/event/models/event_registration.py
Expand Up @@ -162,10 +162,11 @@ def write(self, vals):

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)
Expand Down
8 changes: 3 additions & 5 deletions addons/event/models/event_ticket.py
Expand Up @@ -163,11 +163,10 @@ def _check_seats_availability(self, minimal_availability=0):
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
Expand All @@ -179,8 +178,7 @@ def name_get(self):
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
Expand Down
5 changes: 3 additions & 2 deletions addons/fleet/models/fleet_vehicle_assignation_log.py
Expand Up @@ -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}'

0 comments on commit 24a617b

Please sign in to comment.