113 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Monkey patch для django-scheduler: исправление бага с byweekday.
ПРОБЛЕМА:
---------
Когда событие создается в день, который входит в byweekday,
django-scheduler заменяет весь массив byweekday на только этот день.
ПРИМЕР БАГА:
- Создаем событие в пятницу (weekday = 4)
- Выбираем byweekday = [1, 4] (вторник и пятница)
- django-scheduler видит: 4 in [1, 4] = True
- Результат: event_params['byweekday'] = [4] вместо [1, 4]
- События создаются только в пятницу, вторник игнорируется
КОД БАГА (schedule/models/events.py, строки 375-378):
if sp == rule_params[param] or (
hasattr(rule_params[param], "__iter__") and sp in rule_params[param]
):
event_params[param] = [sp] # ← БАГ!
РЕШЕНИЕ:
--------
Переопределяем Event._event_params() с исправленной логикой для byweekday.
Используем ленивый импорт чтобы избежать проблем с порядком загрузки Django.
"""
import logging
logger = logging.getLogger(__name__)
def create_patched_method():
"""Создаёт пропатченный метод с ленивым импортом констант."""
# Ленивый импорт - только при создании метода
from schedule.models.events import freq_dict_order, param_dict_order
def patched_event_params(self):
"""
Исправленная версия Event._event_params().
Для byweekday с несколькими днями НЕ заменяем массив,
если день начала входит в него.
"""
freq_order = freq_dict_order[self.rule.frequency]
rule_params = self.event_rule_params
start_params = self.event_start_params
event_params = {}
if len(rule_params) == 0:
return event_params
for param in rule_params:
if (
param in param_dict_order
and param_dict_order[param] > freq_order
and param in start_params
):
sp = start_params[param]
# ИСПРАВЛЕНИЕ: Для byweekday не заменяем массив
if param == "byweekday" and hasattr(rule_params[param], "__iter__"):
event_params[param] = rule_params[param]
elif sp == rule_params[param] or (
hasattr(rule_params[param], "__iter__") and sp in rule_params[param]
):
event_params[param] = [sp]
else:
event_params[param] = rule_params[param]
else:
event_params[param] = rule_params[param]
return event_params
return patched_event_params
# Флаг для предотвращения повторного применения патча
_patch_applied = False
def apply_patch():
"""Применяет патч к django-scheduler Event модели."""
global _patch_applied
# Если патч уже применён, пропускаем
if _patch_applied:
return True
try:
# Ленивый импорт - только при вызове apply_patch()
from schedule.models import Event
# Создаём и применяем пропатченный метод
patched_method = create_patched_method()
Event._event_params = patched_method
logger.info(
"django-scheduler compatibility patch applied",
extra={
"event": "scheduling.patch.applied",
"patched_method": patched_method.__name__,
},
)
_patch_applied = True
return True
except Exception:
logger.exception(
"Failed to apply django-scheduler compatibility patch",
extra={"event": "scheduling.patch.failed"},
)
return False