You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Odoo模块关联现有PostgreSQL表时视图字段报错求助

Odoo关联现有PostgreSQL表时视图字段不存在问题解决

问题背景

开发Odoo模块测试CRUD功能,尝试关联已创建的两个PostgreSQL表。最初使用数据库视图仅能读取数据,无法执行增删改操作,因此改为直接使用真实表,但配置后启动服务器报错。

现有代码

models.py

from odoo import models, fields

class PcClientes(models.Model):
    _name = 'clientes.pc_clientes'
    _description = 'Clientes PC'
    _table = 'pc_clientes'  # Nombre de la tabla en la base de datos
    _auto = False  # No queremos que Odoo cree la tabla automáticamente, ya existe

    # Campos de la tabla pc_clientes
    xempgen_id = fields.Char(string='EmpGen ID', required=True)
    xcliente_id = fields.Char(string='Cliente ID', required=True)
    xcod_postal = fields.Char(string='Código Postal')
    xdomicilio = fields.Char(string='Domicilio')
    xnif = fields.Char(string='NIF')
    xnif_ue = fields.Char(string='NIF UE')
    xnomabrev = fields.Char(string='Nombre Abreviado')
    xnombre = fields.Char(string='Nombre', required=True)
    xpais_id = fields.Char(string='ID País')
    xper_fiscal = fields.Char(string='Período Fiscal')
    xpoblacion = fields.Char(string='Población')
    xprovincia_id = fields.Char(string='ID Provincia')
    xlatitud = fields.Float(string='Latitud')
    xlongitud = fields.Float(string='Longitud')
    trial723 = fields.Char(string='Trial723')

    # Relación con la tabla pl_clientes
    pl_cliente_id = fields.Many2one(
        'clientes.pl_clientes', 
        string="PL Cliente", 
        ondelete='cascade', 
        required=True
    )

class PlClientes(models.Model):
    _name = 'clientes.pl_clientes'
    _description = 'Clientes PL'
    _table = 'pl_clientes'  # Nombre de la tabla en la base de datos
    _auto = False  # No queremos que Odoo cree la tabla automáticamente, ya existe

    # Campos de la tabla pl_clientes
    xcliente_id = fields.Char(string='Cliente ID', required=True)
    xcod_docto = fields.Char(string='Código Documento')
    xcopias_alb = fields.Integer(string='Copias Albarán')
    xcopias_fact = fields.Integer(string='Copias Factura')
    xmodalidad_id = fields.Char(string='ID Modalidad')
    xpor_comision = fields.Float(string='Porcentaje Comisión')
    xreferencia = fields.Char(string='Referencia')
    xrepresentante_id = fields.Char(string='ID Representante')
    xsecpref_id = fields.Char(string='ID SecPref')
    xtipo_fact = fields.Integer(string='Tipo de Factura', required=True)
    xempgen_id = fields.Char(string='EmpGen ID', required=True)
    xempresa_id = fields.Char(string='Empresa ID', required=True)
    xfax = fields.Char(string='Fax')
    xtelefono = fields.Char(string='Teléfono')
    xemail = fields.Char(string='Email')
    xfecha_alta = fields.Datetime(string='Fecha Alta')
    xfecha_baja = fields.Datetime(string='Fecha Baja')
    xinternet = fields.Char(string='Internet')
    xlangage = fields.Integer(string='Lenguaje')
    xlangage_remplace = fields.Integer(string='Lenguaje Reemplazado')
    xcopias_ped = fields.Integer(string='Copias Pedido')
    xcredito = fields.Float(string='Crédito')
    xctacon = fields.Char(string='Cta Con')
    xctamayor = fields.Char(string='Cta Mayor')
    xcyc_activo = fields.Integer(string='Cyc Activo')
    xcyc_poliza = fields.Char(string='Cyc Póliza')
    xdivisa_id = fields.Char(string='ID Divisa')
    xdto_com = fields.Float(string='Dto. Comercial')
    xcoment_albaran = fields.Char(string='Comentario Albarán')
    xcoment_factura = fields.Char(string='Comentario Factura')
    xcoment_pedido = fields.Char(string='Comentario Pedido')
    xcontacto = fields.Char(string='Contacto')
    xagrupa_alb = fields.Integer(string='Agrupa Albarán')
    xalb_valorado = fields.Integer(string='Albarán Valorador')
    xalta_modif = fields.Integer(string='Alta Modificada')
    xcalificacion_id = fields.Char(string='ID Calificación')
    xcargo = fields.Char(string='Cargo')
    xrecibe_facturae = fields.Integer(string='Recibe Facturae')
    xxjuego_id = fields.Char(string='ID Juego')
    p856_tipo_tarifa = fields.Char(string='Tipo Tarifa')
    p856_dto_metraje = fields.Float(string='Dto. Metraje')
    p856_dto_tarifa = fields.Float(string='Dto. Tarifa')
    p856_agen_com_id = fields.Char(string='Agente Com')
    p856_eti_metr_ext = fields.Char(string='Etiqueta Metr Ext')
    p856_observaciones = fields.Char(string='Observaciones')
    p856_cadena = fields.Char(string='Cadena')
    p856_credito_aseg = fields.Float(string='Crédito Asegurado')
    p856_credito_rioma = fields.Float(string='Crédito Rioma')
    p856_crm_id = fields.Char(string='ID CRM')
    p856_modificado = fields.Integer(string='Modificado')
    p856_modificado_r = fields.Integer(string='Modificado R')
    p856_dto_met_max = fields.Float(string='Dto. Metraje Max')
    p856_dto_pie_max = fields.Float(string='Dto. Pie Max')
    p856_entite = fields.Char(string='Entidad')
    p856_pass_crm = fields.Char(string='Pass CRM')
    p856_cerrado = fields.Integer(string='Cerrado')
    p856_supervisor = fields.Char(string='Supervisor')
    p856_tipo_cliente = fields.Integer(string='Tipo Cliente')
    p856_fact_ftp = fields.Integer(string='Fact. FTP')
    p856_backoffice_id = fields.Char(string='ID Backoffice')
    trial726 = fields.Char(string='Trial 726')

    # Relación con la tabla pc_clientes
    pc_cliente_id = fields.Many2one(
        'clientes.pc_clientes', 
        string="PC Cliente", 
        ondelete='cascade', 
        required=True
    )

视图代码(templates.xml)

<odoo>
    <data>

      <record id="clientes_list_view" model="ir.ui.view">
        <field name="name">clientes.list.view</field>
        <field name="model">clientes.pc_clientes</field>
        <field name="arch" type="xml">
          <list>
            <field name="xempgen_id"/>
            <field name="xcliente_id"/>
            <field name="xnomabrev"/>
            <field name="xnombre"/>
            <field name="pl_cliente_id.xfax"/>
          </list>
        </field>
      </record>

      <record id="clientes_form_view" model="ir.ui.view">
        <field name="name">clientes.form.view</field>
        <field name="model">clientes.pc_clientes</field>
        <field name="arch" type="xml">
          <form>
          <group name="Datos indicativos" string="Datos indicativos" class="central">

            <group>
              <field name="xnombre" class="field"/>
            </group>
            <group>
              <field name="xnomabrev" class="field"/>
            </group>
            <group>
              <field name="xreferencia" class="field"/>
            </group>
              <field name="pl_cliente_id.xfax" class="field"/>
            <group/>

          </group>
          </form>
        </field>
      </record>

      <record id="clientes_action" model="ir.actions.act_window">
        <field name="name">Clientes</field>
        <field name="res_model">clientes.pc_clientes</field>
        <field name="view_mode">list,form</field>
      </record>

      <menuitem id="menu_root" name="Rioma"/>
      <menuitem id="menu_clientes" name="Clientes" parent="menu_root"/>
      <menuitem id="menu_clientes_list" name="Clientes List"
      parent="menu_clientes" action="clientes_action"/>
      
    </data>
</odoo>

报错信息

Error while validating view near:

            <field name="xnombre"/>
            <field name="pl_cliente_id.xfax"/>
          </list>
Field "pl_cliente_id.xfax" does not exist in model "clientes.pc_clientes"

View error context:
{'file': 'c:\\odoo\\modules\\clientes\\views\\templates.xml',
 'line': 7,
 'name': 'clientes.list.view',
 'view': ir.ui.view(878,),
 'view.model': 'clientes.pc_clientes',
 'view.parent': ir.ui.view(),
 'xmlid': 'clientes_list_view'}

解决方案

1. 修正Many2one字段的关联配置

因为使用_auto=False,Odoo无法自动识别现有数据库表的外键关系,必须显式指定Many2one字段对应的数据库列:

  • 假设pc_clientes表中存储pl_clientes记录ID的字段名为pl_cliente_id,修改PcClientes类中的关联字段:
    pl_cliente_id = fields.Many2one(
        'clientes.pl_clientes', 
        string="PL Cliente", 
        ondelete='cascade', 
        required=True,
        column='pl_cliente_id'  # 对应数据库表中的外键字段名
    )
    
  • 同理,PlClientes类中的pc_cliente_id字段也要添加column参数,对应pl_clientes表中的外键字段名。

2. 优化视图中关联字段的显示方式

可以通过两种方式解决视图字段识别问题:

  • 方式一:添加related字段
    在PcClientes模型中添加一个关联字段,直接映射pl_clientes的xfax字段:
    pl_cliente_fax = fields.Char(string="Fax PL Cliente", related='pl_cliente_id.xfax', store=False)
    
    然后在视图中替换为:
    <field name="pl_cliente_fax"/>
    
  • 方式二:确保关联字段配置正确后刷新模块
    修正Many2one字段的column参数后,重启Odoo服务并升级模块,Odoo会重新识别字段关联关系,此时pl_cliente_id.xfax的写法即可生效。

3. 关键注意事项

  • 确保PostgreSQL表pc_clientes和pl_clientes中存在对应对方ID的字段,且字段名与模型中column参数指定的一致。
  • 使用_auto=False时,模型中定义的字段必须与数据库表的字段名完全匹配(注意PostgreSQL的大小写敏感设置)。
  • 修改模型后必须重启Odoo并升级模块,否则元数据不会更新。

内容的提问来源于stack exchange,提问作者David Carmona Arrabal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 00:09:49