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

Odoo13重写create方法批量生成记录报AttributeError如何解决?

问题根因

你的两个猜测都正确,核心错误有3个:

  • @api.model装饰的create方法执行时,新记录还没写入数据库,self是空记录集,所以self.employ_id、self.begin_date全部为None,你的分支判断根本进不去,最终方法没有显式返回值,默认返回None,Odoo框架要读取返回记录的id时就触发了报错。
  • 就算进入循环,你把return写在for循环内部,第一次循环创建完第一条记录就直接返回了,无法创建所有日期的记录。
  • 你在循环中每次都覆盖了vals,也没有保留其他字段的传入值(比如day_hours等)。
修正后的完整代码
from datetime import timedelta, datetime, date
from calendar import monthrange

from odoo import api, fields, models, tools
from odoo.exceptions import UserError, AccessError, ValidationError
from odoo.tools import date_utils


class TimeOff(models.Model):
    _name = 'project.timeoff'
    _rec_name = 'employ_id'

    employ_id = fields.Many2one('hr.employee', string='Employee', required=True)
    date = fields.Date('Date', required=True, index=True, default=fields.Date.context_today)
    begin_date = fields.Datetime('First Day of Leave', required=True)
    day_hours = fields.Integer('Off hours per day', default=8, required=True)
    end_date = fields.Datetime('Last Day of Leave', required=True) # 建议加上必填,避免空值异常

    @api.model
    def create(self, vals):
        # 从传入的vals中取值,不要用self
        employ_id = vals.get('employ_id')
        begin_date = vals.get('begin_date')
        end_date = vals.get('end_date')
        day_hours = vals.get('day_hours', 8)

        # 先校验必填参数,参数不全走默认创建逻辑
        if not all([employ_id, begin_date, end_date]):
            return super(TimeOff, self).create(vals)

        # 计算日期范围
        range_date = self.calc_dates(begin_date, end_date, mode='date')
        if not range_date:
            raise ValidationError("结束日期不能早于开始日期")
        
        # 构造所有要创建的记录的vals列表
        create_vals_list = []
        for day in range_date:
            create_vals = vals.copy() # 保留原始传入的其他字段
            create_vals.update({
                'date': day, # 补充必填的date字段赋值
                'begin_date': day,
            })
            create_vals_list.append(create_vals)
        
        # 批量创建所有记录,返回创建的结果给框架
        return super(TimeOff, self).create(create_vals_list)

    @api.model # 改成api.model,不需要依赖当前记录
    def calc_dates(self, date1, date2, mode='date'):
        date_from = fields.Date.from_string(date1)
        date_to = fields.Date.from_string(date2)

        delta = date_to - date_from
        if delta.days < 0: 
            return None

        dates = []
        for n in range(delta.days + 1):
            current_day = date_from + timedelta(days=n)
            if mode == 'date':
                dates.append(current_day)
            if mode == 'string':
                dates.append(fields.Date.to_string(current_day))
        return dates
关键修改说明
  • 所有参数从vals中读取,不再使用空的self取值
  • 调整了return逻辑,所有分支都有返回值:如果参数不全则走默认创建逻辑,参数齐全则批量创建所有日期的记录后返回完整记录集
  • 保留了原始vals中的其他字段值,避免字段数据丢失
  • 给calc_dates加上了@api.model装饰,支持无记录上下文调用
  • 补充了必填的date字段赋值,避免创建时报必填校验错误

内容的提问来源于stack exchange,提问作者for-loop

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 07:45:02