Odoo 14自定义登录页:新增contact_no字段实现优先该字段用户认证
Odoo 14 基于自定义contact_no字段的登录认证实现指南
前置已完成工作
你目前已经完成的配置如下:
- 模型层:继承
res.users模型新增contact_no字段完成基础存储配置 - 视图层:通过XPath继承
web.login模板,在邮箱输入框前渲染了Contact No输入项,页面展示正常
已可正常运行的自定义登录模板代码如下:
<template id="login" inherit_id="web.login" name="Custom Login" > <xpath expr="//div[hasclass('field-login')]" position="before"> <div class="form-group field-contact-no"> <label for="contact_no">Contact No</label> <input type="text" placeholder="Contact No" name="contact_no" t-att-value="contact_no" id="contact_no" t-attf-class="form-control #{'form-control-sm' if form_small else ''}" required="required" autofocus="autofocus" autocapitalize="off"/> </div> </xpath> </template>
需要补充的核心调整
要实现点击登录后优先用contact_no字段完成身份认证,不需要改动Odoo原有的密码校验、session生成核心流程,只要在请求进入原认证逻辑前做好账号映射即可,分别调整控制器逻辑、可选补充模型约束就能落地。
1. 控制器层逻辑改写
Odoo 14默认的登录POST接口为web模块下Home控制器的/web/login路由,我们需要通过继承该控制器重写登录处理逻辑,核心流程为:
- 从POST请求参数中读取用户提交的
contact_no值 - 优先在
res.users表中匹配该值对应的有效活跃用户 - 如果匹配到唯一有效用户,将该用户绑定的系统登录账号(即原有login字段存储的邮箱值)作为认证账号,传入原系统的标准认证流程
- 如果未匹配到对应contact_no的用户,自动回退到原有“邮箱+密码”的默认认证逻辑,不影响原有账号的登录能力
参考实现代码:
from odoo import http from odoo.addons.web.controllers.home import Home from odoo.http import request class CustomAuthHome(Home): @http.route('/web/login', type='http', auth="none", methods=['POST'], csrf=False, save_session=False) def web_login(self, redirect=None, **kw): # 提取请求中的联系号码参数 input_contact_no = kw.get('contact_no', '').strip() if input_contact_no: # 按联系号码匹配有效用户 matched_user = request.env['res.users'].sudo().search([ ('contact_no', '=', input_contact_no), ('active', '=', True) ], limit=1) if matched_user: # 用匹配到的用户邮箱替换原认证逻辑的login入参 kw['login'] = matched_user.login # 调用原父类认证逻辑,完成后续密码校验、session创建 return super(CustomAuthHome, self).web_login(redirect, **kw)
2. 模型层补充约束(可选但推荐)
为了避免一个contact_no绑定多个用户导致的认证歧义、提升查询性能,建议在继承res.users时给contact_no字段增加索引和唯一约束:
from odoo import models, fields class ResUsersInherit(models.Model): _inherit = 'res.users' contact_no = fields.Char( string='联系号码', index=True, # 给字段加数据库索引,提升匹配查询速度 copy=False ) _sql_constraints = [ ('unique_contact_no', 'unique(contact_no)', '联系号码不能重复绑定多个系统账号') ]
落地注意事项
- 必须保留原有邮箱登录的兜底逻辑,避免自定义逻辑出现问题时阻断全量用户登录
- 确保模板中contact_no输入框的
name属性和控制器中读取的参数名完全一致,否则会出现参数取不到的问题 - 登录错误提示逻辑保持和原系统一致,不要额外自定义突兀的报错逻辑,降低用户使用困惑
- 用户量较大的场景下,不要在控制器里写复杂的关联查询,优先靠索引加速单表匹配
内容的提问来源于stack exchange,提问作者Oralover
相关产品推荐
相关产品推荐

