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
相关产品推荐
相关产品推荐

