When creating a new record on the odoo page, the front-end will call the default_get function of the back-end model through rpc to obtain the corresponding field default values based on the field list passed in by the front-end.
#odoo/models.py @api.model def default_get(self, fields_list): """ default_get(fields_list) -> default_values Return default values for the fields in ``fields_list``. Default values are determined by the context, user defaults, and the model itself. :param list fields_list: names of fields whose default is requested :return: a dictionary mapping field names to their corresponding default values, if they have a default value. :rtype: dict .. note:: Unrequested defaults won't be considered, there is no need to return a value for fields whose names are not in `fields_list`. \t\t """ defaults = {<!-- -->} parent_fields = defaultdict(list) ir_defaults = self.env['ir.default'].get_model_defaults(self._name) for name in fields_list: # 1. look up context key = 'default_' + name if key in self._context: defaults[name] = self._context[key] continue # 2. look up ir.default if name in ir_defaults: defaults[name] = ir_defaults[name] continue field = self._fields.get(name) # 3. look up field.default if field and field.default: defaults[name] = field.default(self) continue # 4. delegate to parent model if field and field.inherited: field = field.related_field parent_fields[field.model_name].append(field.name) # convert default values to the right format # # we explicitly avoid using _convert_to_write() for x2many fields, # because the latter leaves values like [(Command.LINK, 2), # (Command.LINK, 3)], which are not supported by the web client as # default values; stepping through the cache allows to normalize # such a list to [(Command.SET, 0, [2, 3])], which is properly # supported by the web client for fname, value in defaults.items(): if fname in self._fields: field = self._fields[fname] value = field.convert_to_cache(value, self, validate=False) defaults[fname] = field.convert_to_write(value, self) # add default values for inherited fields for model, names in parent_fields.items(): defaults.update(self.env[model].default_get(names)) return defaults
1. The function of this function
The function documentation explains it very clearly, so I will repeat it again. This function returns the default value of the response based on the field name passed in. The default value is determined by context, user definition, and the model itself. Input parameters: field_list field name list. Return value: a dictionary, key is the field name, value is the default value of the field Note: This function only returns the default values for the fields in the requested list. As for which fields are there, it is determined by the front-end view.
2. Four ways to set default values
As you can see from the code, there are four ways to get the default value of the dictionary according to priority:
2.1 Context
action
<record id="action_move_out_invoice_type" model="ir.actions.act_window"> <field name="name">Invoices</field> <field name="res_model">account.move</field> <field name="view_mode">tree,kanban,form</field> <field name="view_id" ref="view_out_invoice_tree"/> <field name="search_view_id" ref="view_account_invoice_filter"/> <field name="domain">[('move_type', '=', 'out_invoice')]</field> <field name="context">{<!-- -->'default_move_type': 'out_invoice'}</field> <field name="help" type="html"> <p class="o_view_nocontent_smiling_face"> Create a customer invoice </p><p> Create invoices, register payments and keep track of the discussions with your customers. </p> </field> </record>
2.2 ir.default
@api.model def get(self, model_name, field_name, user_id=False, company_id=False, condition=False): """ Return the default value for the given field, user and company, or ``None`` if no default is available. :param model_name: :param field_name: :param user_id: may be ``False`` for all users, ``True`` for the current user, or any user id :param company_id: may be ``False`` for all companies, ``True`` for the current user's company, or any company id :param condition: optional condition that restricts the applicability of the default value; this is an opaque string, but the client typically uses single-field conditions in the form ``'key=val'``. """ if user_id is True: user_id = self.env.uid if company_id is True: company_id = self.env.company.id field = self.env['ir.model.fields']._get(model_name, field_name) default = self.search([ ('field_id', '=', field.id), ('user_id', '=', user_id), ('company_id', '=', company_id), ('condition', '=', condition), ], limit=1) return json.loads(default.json_value) if default else None
Judging from the code, you can set different default values for a certain dictionary in the model according to different users, companies, and conditions.
But it is rarely used in actual development.
Default value of 2.3 fields
This is the most common way to set default values
There are three setting methods:
1. Direct setting
active = fields.Boolean(default=True)
2. Set as a function
example_date = fields.Date(string='Date example', default=_default_example_date, store=False)
3 Set as lambda function
user_id = fields.Many2one('res.users', default= lambda self: self.env.user)
2.4 Default value of parent table inherited through delegation (_inherits)
Regarding delegated inheritance, we will not describe it in detail here. A simple understanding is that the data is stored in the parent table, but can be used as its own fields.
Association through a many2one field.
3 Override default_get
In some scenarios, we can rewrite this function in the model and add our own logic, such as:
def default_get(self, fields_list): # Call the parent class method first defaults = super().default_get(fields_list) # Then execute your own logic to modify defaults, and finally return it. if 'journal_id' in defaults and 'date' in fields_list: last_line = self.search([ ('journal_id', '=', defaults.get('journal_id')), ('state', '=', 'posted'), ], limit=1) statement = last_line.statement_id if statement: defaults.setdefault('date', statement.date) elif last_line: defaults.setdefault('date', last_line.date) return defaults