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

Python中值变化时触发函数的实现方法及Odoo假期池计算方法修改需求

1. How to Trigger a Function When a Value Changes in Python

Depending on your scenario, there are a few practical ways to achieve this:

Using Python Properties

For simple class attributes, properties are the most straightforward approach. You can define a setter that checks if the new value differs from the old one, then fires your target function:

class MyClass:
    def __init__(self):
        self._value = None

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, new_val):
        if new_val != self._value:
            self._value = new_val
            self._on_value_change()

    def _on_value_change(self):
        print("Value updated! Triggering related logic...")

Observer Pattern

If multiple components need to react to value changes, the observer pattern is ideal. It lets you register "observers" that get notified whenever the value updates:

class ObservableValue:
    def __init__(self):
        self._observers = []
        self._current_value = None

    @property
    def value(self):
        return self._current_value

    @value.setter
    def value(self, new_val):
        if new_val != self._current_value:
            self._current_value = new_val
            self._notify_observers()

    def add_observer(self, observer):
        self._observers.append(observer)

    def _notify_observers(self):
        for observer in self._observers:
            observer.on_value_update(self._current_value)

class ValueObserver:
    def on_value_update(self, value):
        print(f"Received updated value: {value}")

# Example usage
my_value = ObservableValue()
observer = ValueObserver()
my_value.add_observer(observer)
my_value.value = 42  # Triggers the observer's update method

Odoo-Specific Methods

Since your second question relates to Odoo, here's how to handle field changes in the Odoo ecosystem:

  • Computed Fields: Use the @api.depends decorator to trigger a computed method when specific fields change.
  • Override Write: Override the write method to compare old and new field values, then run your logic if a change is detected.
  • Tracking: Add tracking=True to a field to log changes, then react to those logs in related methods.

2. Modifying Your Odoo Method

Let's break down your requirement: you want to skip action when annual_leave changes, but increment remaining_count (from your holiday pool) when it doesn't. Here's how to adjust your code:

Assumptions

  • annual_leave is a field on your model (we'll cover an alternative if you meant the annual holiday count from the search below).
  • You want to add 1 to remaining_count when setting current_holiday_pool only if annual_leave hasn't changed.

Step 1: Update the Depends Decorator

First, ensure your computed method triggers when annual_leave changes by adding it to the @api.depends list:

@api.multi
@api.depends('yearly_holidays_ids', 'annual_leave')  # Add annual_leave here
def _get_current_holiday_pool(self):

Step 2: Check for Changes and Adjust Logic

Use Odoo's has_changed method to detect if annual_leave was modified in the current write operation. Then adjust the current_holiday_pool calculation accordingly:

from odoo import api, models, fields
import datetime

class YourModel(models.Model):
    _name = 'your.model.name'  # Replace with your actual model name

    annual_leave = fields.Integer(string='Annual Leave')
    current_holiday_pool = fields.Float(compute='_get_current_holiday_pool', store=True, string='Current Holiday Pool')
    yearly_holidays_ids = fields.One2many('yearly.holidays', 'related_model_id', string='Yearly Holidays')

    @api.multi
    @api.depends('yearly_holidays_ids', 'annual_leave')
    def _get_current_holiday_pool(self):
        for record in self:
            # Skip logic if annual_leave changed in this write
            if record.has_changed('annual_leave'):
                continue

            current_year = datetime.date.today().year
            total_holidays = record.yearly_holidays_ids.filtered(lambda lm: lm.year == current_year)
            annual_leaves_count = self.env['hr.holidays'].search_count([('holiday_status_id.name', '=', 'annual')])

            if annual_leaves_count > 1:
                if total_holidays:
                    record.current_holiday_pool = total_holidays[0].remaining_count + 1
            elif annual_leaves_count == 1:
                if total_holidays:
                    record.current_holiday_pool = total_holidays.remaining_count + 1
            else:
                record.current_holiday_pool = 0

Alternative: If annual_leave refers to the search count

If you meant the annual_leaves_count from the search_count call instead of a model field, you'll need to store the previous count to compare. Add a field like last_annual_leaves_count to track it:

last_annual_leaves_count = fields.Integer(string='Last Annual Leaves Count', store=True)

@api.multi
@api.depends('yearly_holidays_ids')
def _get_current_holiday_pool(self):
    for record in self:
        current_year = datetime.date.today().year
        total_holidays = record.yearly_holidays_ids.filtered(lambda lm: lm.year == current_year)
        annual_leaves_count = self.env['hr.holidays'].search_count([('holiday_status_id.name', '=', 'annual')])

        # Compare current count with stored last count
        if annual_leaves_count != record.last_annual_leaves_count:
            record.last_annual_leaves_count = annual_leaves_count
            continue

        # Increment remaining_count since the count didn't change
        if annual_leaves_count > 1:
            if total_holidays:
                record.current_holiday_pool = total_holidays[0].remaining_count + 1
        elif annual_leaves_count == 1:
            if total_holidays:
                record.current_holiday_pool = total_holidays.remaining_count + 1
        else:
            record.current_holiday_pool = 0

Key Notes

  • The has_changed method only works during write operations; use a stored field if you need to track changes across sessions.
  • Always handle empty total_holidays to avoid AttributeErrors.
  • Add store=True to current_holiday_pool if you want to persist the computed value.

内容的提问来源于stack exchange,提问作者SaltySteven

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 14:57:32