One uncommon and potent ORM technique in Odoo that offers comprehensive metadata information about a model's fields is fields_get(). Fields_get() returns structural information about field definitions, such as their types, labels, constraints, and relationships, in contrast to other ORM methods that work with record data. Building dynamic forms, developing introspection tools, verifying field requirements, and creating API integrations that require programmatic understanding of model structures all require this approach.
What is the Fields_get() Method?
A dictionary with comprehensive details about every field (or just the requested fields) in a model is returned by the fields_get() method. It offers a variety of attributes, including field type, string label, help text, selection options, relational data, and whether it's necessary. Data validation, API documentation, dynamic user interface creation, and runtime model structure comprehension all depend on this metadata.
Syntax:
Model.fields_get(allfields=None, attributes=None)
Parameters:
- allfields: List of field names to retrieve information for. If None or not provided, returns information for all fields.
- attributes: List of attribute names to include in the response. If None, returns all available attributes.
Returns: A dictionary where keys are field names and values are dictionaries containing field metadata.
Basic Usage
Get All Fields with All Attributes
# Get complete field information for all fields
partner_fields = self.env['res.partner'].fields_get()
# Result structure:
# {
# 'name': {
# 'type': 'char',
# 'string': 'Name',
# 'required': True,
# 'size': 128,
# 'help': False,
# ...
# },
# 'email': {
# 'type': 'char',
# 'string': 'Email',
# 'required': False,
# ...
# },
# ...
# }
Get Specific Fields Only
# Get information only for specific fields
specific_fields = self.env['res.partner'].fields_get(
allfields=['name', 'email', 'phone', 'country_id']
)
# Returns information for only these four fields
Get Specific Attributes Only
# Get only certain attributes for all fields
limited_info = self.env['res.partner'].fields_get(
attributes=['string', 'type', 'required']
)
# Result for each field contains only: string, type, required
# {
# 'name': {
# 'type': 'char',
# 'string': 'Name',
# 'required': True
# },
# ...
# }
Combine Both Parameters
# Get specific attributes for specific fields
result = self.env['sale.order'].fields_get(
allfields=['partner_id', 'date_order', 'amount_total'],
attributes=['string', 'type', 'readonly', 'required']
)
Understanding Field Metadata Attributes
For every field, the fields_get() method returns a large number of attributes. Effective use of this method requires an understanding of these characteristics.
Typical Field Features
Fundamental Qualities:
- type: Field type (char, integer, float, boolean, date, datetime, selection, many2one, one2many, many2many, etc.)
- string: Human-readable label for the field
- help: Help text or tooltip description
- required: Whether the field is mandatory (True/False)
- readonly: Whether the field is read-only (True/False)
Limitations and Verification:
- size: Char fields' maximum length
- digits: Float field precision specification (tuple: total digits, decimal places)
- Fields of Selection:
Selection Fields:
- selection: A list of choices for the selection fields
Relational Fields:
- relation: Target model name for relational fields
- relation_field: Inverse field name for one2many fields
- domain: Domain filter for relational fields
Other Attributes:
- default: Default value for the field
- store: Whether field is stored in database
- searchable: Whether field can be used in search domains
- sortable: Whether field can be used for sorting
- translate: Whether field supports multi-language translation
- company_dependent: Whether field values are company-specific
Overriding fields_get() for Dynamic Field Behavior
One of its most powerful applications is overriding fields_get() to dynamically modify field attributes according to business logic. You can provide UI customization and field-level security without altering views by overriding this method. Depending on user roles, company settings, or any runtime condition, you can alter the labels of fields, make them read-only, hide them completely, or change other properties.
Role-Based Field Security, for instance
This real-world example demonstrates how to override fields_get() and add dynamic field-level security to the Sales Order model:
from odoo import api, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
@api.model
def fields_get(self, allfields=None, attributes=None):
"""
Override fields_get to apply role-based field security
"""
# Get standard field metadata
res = super().fields_get(allfields, attributes)
# Make discount field readonly for non-managers
if 'discount' in res:
if not self.env.user.has_group('sales_team.group_sale_manager'):
res['discount']['readonly'] = True
# Hide margin field completely from non-managers
if 'margin' in res:
if not self.env.user.has_group('sales_team.group_sale_manager'):
del res['margin'] # Remove field from metadata
return res
This approach ensures consistent field behavior across all access methods (UI, API, imports) without requiring view inheritance. The discount field is made read-only for normal users, while the margin field is completely hidden from non-managers using dynamic security based on user roles.
Use Case: Determine Necessary Fields
def get_required_fields(self, model_name):
"""
Get list of all required fields for a model
"""
model = self.env[model_name]
all_fields = model.fields_get(attributes=['required', 'string'])
required_fields = []
for field_name, field_info in all_fields.items():
if field_info.get('required', False):
required_fields.append({
'name': field_name,
'label': field_info.get('string', field_name)
})
return required_fields
# Usage example
required = get_required_fields('sale.order')
# Returns: [
# {'name': 'partner_id', 'label': 'Customer'},
# {'name': 'date_order', 'label': 'Order Date'},
# ...
# ]
When to Apply This Method
When to use fields_get()
- Creating dynamic user interfaces that require no code updates to adjust to model changes
- To guarantee schema compliance, external data must be validated prior to import operations.
- Developing general tools that don't require hardcoded field knowledge and function across various models
- Automatically producing documentation based on model definitions
- Adding introspection capabilities to developer tools or admin panels
- Creating API integrations requires knowledge of the fields that are available and their limitations.
Standard ORM techniques in Odoo handle basic field operations, but a different strategy is needed to programmatically comprehend model structures. This feature is offered by the fields_get() method, which lets programmers create clever, flexible apps that react to schema changes on their own. When used properly in conjunction with standard ORM operations, it guarantees data validation, facilitates dynamic user interface generation, and permits sophisticated introspection across the system.
Fields_get() gives developers the ability to create generic tools, validate data before operations, generate documentation automatically, and create integrations that adjust to model structures by providing full field metadata in a standardized format. Fields_get() is the uncommon but crucial function that enables model-aware programming in Odoo 19, whether you're developing dynamic forms, import wizards, API documentation generators, or schema introspection tools.
To read more about Complete Overview of Rare ORM Methods in Odoo 19, refer to our blog Complete Overview of Rare ORM Methods in Odoo 19.