Files
diary-family/core/tasks.py

149 lines
4.5 KiB
Python
Raw Normal View History

2026-01-04 19:17:33 +08:00
from celery import shared_task
from django.utils import timezone
from datetime import timedelta
from django.core.mail import EmailMessage
from django.conf import settings
from django.shortcuts import render
import os
from loguru import logger
# WeasyPrint可用性标记初始为None
WEASYPRINT_AVAILABLE = None
# 获取WeasyPrint可用性
def is_weasyprint_available():
"""检查WeasyPrint是否可用"""
global WEASYPRINT_AVAILABLE
if WEASYPRINT_AVAILABLE is None:
try:
from weasyprint import HTML
WEASYPRINT_AVAILABLE = True
except ImportError:
logger.warning("WeasyPrint库无法导入PDF功能将不可用")
WEASYPRINT_AVAILABLE = False
return WEASYPRINT_AVAILABLE
from .models import (
ReadingRecord,
InsightRecord,
FamilyTask,
TodayPlan,
SystemConfig
)
@shared_task
def generate_daily_pdf_report():
"""生成每日PDF报告"""
logger.info("开始执行每日PDF报告生成任务")
2026-01-04 19:17:33 +08:00
# 检查WeasyPrint是否可用
if not is_weasyprint_available():
logger.error("WeasyPrint库不可用无法生成PDF报告")
return False
today = timezone.now().date()
today_str = today.strftime('%Y-%m-%d')
# 生成报告数据
report_date = today
yesterday = report_date - timedelta(days=1)
# 获取昨日记录
yesterday_reading = ReadingRecord.objects.filter(date=yesterday)
yesterday_insight = InsightRecord.objects.filter(date=yesterday)
# 获取今日计划
today_plan = TodayPlan.objects.filter(date=report_date)
# 获取家庭事项统计
from django.db.models import Count
family_task_stats = FamilyTask.objects.values('type').annotate(count=Count('id'))
# 准备上下文
context = {
'today': report_date,
'yesterday': yesterday,
'yesterday_reading': yesterday_reading,
'yesterday_insight': yesterday_insight,
'today_plan': today_plan,
'family_task_stats': family_task_stats,
}
# 渲染HTML模板
html_string = render(None, 'core/report_pdf.html', context).content.decode('utf-8')
# 生成PDF报告
pdf_file = f"report_{today_str}.pdf"
pdf_path = os.path.join(settings.REPORTS_ROOT, pdf_file)
# 确保报告目录存在
os.makedirs(settings.REPORTS_ROOT, exist_ok=True)
# 生成PDF - 动态导入WeasyPrint
try:
from weasyprint import HTML
HTML(string=html_string).write_pdf(pdf_path)
logger.info(f"PDF报告生成成功: {pdf_path}")
return True
2026-01-04 19:17:33 +08:00
except Exception as e:
logger.error(f"PDF报告生成失败: {str(e)}")
return False
@shared_task
def send_daily_report():
"""发送每日报告"""
logger.info("开始执行每日报告发送任务")
# 先生成PDF报告
pdf_generated = generate_daily_pdf_report()
if not pdf_generated:
logger.error("PDF报告生成失败无法发送邮件")
return False
today = timezone.now().date()
today_str = today.strftime('%Y-%m-%d')
# 获取系统配置
config = SystemConfig.get_config()
# 检查邮件配置是否完整
if not all([config.smtp_server, config.smtp_username, config.smtp_password, config.recipient_email]):
logger.error("邮件配置不完整,无法发送邮件")
return False
2026-01-04 19:17:33 +08:00
# 发送邮件
subject = f"家庭日报 - {today_str}"
message = f"这是您的家庭日报,日期:{today_str}"
from_email = config.smtp_username
recipient_list = [config.recipient_email]
# PDF文件路径
pdf_file = f"report_{today_str}.pdf"
pdf_path = os.path.join(settings.REPORTS_ROOT, pdf_file)
2026-01-04 19:17:33 +08:00
try:
email = EmailMessage(
subject=subject,
body=message,
from_email=from_email,
to=recipient_list,
)
# 添加附件
with open(pdf_path, 'rb') as f:
email.attach(pdf_file, f.read(), 'application/pdf')
# 发送邮件
email.send()
logger.info(f"邮件发送成功,收件人:{config.recipient_email}")
return True
except Exception as e:
logger.error(f"邮件发送失败:{str(e)}")
return False
@shared_task
def debug_task():
"""调试任务用于测试Celery和Redis连接"""
from loguru import logger
logger.info("调试任务执行成功")
return {"status": "success", "message": "Celery任务执行正常", "timestamp": timezone.now().isoformat()}