Files
diary-family/core/views.py

511 lines
16 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.
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse, JsonResponse
from django.utils import timezone
from django.db.models import Count
from django.core.mail import send_mail, EmailMessage
from django.conf import settings
from datetime import timedelta, datetime
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
)
from .forms import (
ReadingRecordForm,
InsightRecordForm,
FamilyTaskForm,
TodayPlanForm,
SystemConfigForm
)
# 首页视图
def index(request):
"""首页"""
logger.info("用户访问首页")
today = timezone.now().date()
yesterday = today - timedelta(days=1)
# 获取昨日记录
yesterday_reading = ReadingRecord.objects.filter(date=yesterday)
yesterday_insight = InsightRecord.objects.filter(date=yesterday)
# 获取今日计划
today_plan = TodayPlan.objects.filter(date=today)
# 获取待处理的家庭事项
pending_family_tasks = FamilyTask.objects.filter(status__name='pending')
context = {
'yesterday': yesterday,
'today': today,
'yesterday_reading': yesterday_reading,
'yesterday_insight': yesterday_insight,
'today_plan': today_plan,
'pending_family_tasks': pending_family_tasks,
}
return render(request, 'core/index.html', context)
# 昨日记录视图
def yesterday_records(request):
"""昨日记录"""
logger.info("用户访问昨日记录页面")
today = timezone.now().date()
yesterday = today - timedelta(days=1)
# 获取昨日阅读记录
reading_records = ReadingRecord.objects.filter(date=yesterday)
# 获取昨日感悟记录
insight_records = InsightRecord.objects.filter(date=yesterday)
context = {
'yesterday': yesterday,
'reading_records': reading_records,
'insight_records': insight_records,
}
return render(request, 'core/yesterday_records.html', context)
# 添加阅读记录
def add_reading(request):
"""添加阅读记录"""
if request.method == 'POST':
form = ReadingRecordForm(request.POST, request.FILES)
if form.is_valid():
reading = form.save(commit=False)
reading.date = timezone.now().date() - timedelta(days=1)
reading.save()
logger.info(f"添加阅读记录: {form.cleaned_data['title']}")
return redirect('yesterday_records')
else:
form = ReadingRecordForm()
context = {'form': form}
return render(request, 'core/add_reading.html', context)
# 编辑阅读记录
def edit_reading(request, pk):
"""编辑阅读记录"""
reading = get_object_or_404(ReadingRecord, pk=pk)
if request.method == 'POST':
form = ReadingRecordForm(request.POST, request.FILES, instance=reading)
if form.is_valid():
form.save()
logger.info(f"编辑阅读记录: {form.cleaned_data['title']}")
return redirect('yesterday_records')
else:
form = ReadingRecordForm(instance=reading)
context = {'form': form, 'reading': reading}
return render(request, 'core/edit_reading.html', context)
# 删除阅读记录
def delete_reading(request, pk):
"""删除阅读记录"""
reading = get_object_or_404(ReadingRecord, pk=pk)
if request.method == 'POST':
reading.delete()
logger.info(f"删除阅读记录: {reading.title}")
return redirect('yesterday_records')
context = {'reading': reading}
return render(request, 'core/delete_reading.html', context)
# 添加感悟记录
def add_insight(request):
"""添加感悟记录"""
if request.method == 'POST':
form = InsightRecordForm(request.POST, request.FILES)
if form.is_valid():
insight = form.save(commit=False)
insight.date = timezone.now().date() - timedelta(days=1)
insight.save()
logger.info("添加感悟记录")
return redirect('yesterday_records')
else:
form = InsightRecordForm()
context = {'form': form}
return render(request, 'core/add_insight.html', context)
# 编辑感悟记录
def edit_insight(request, pk):
"""编辑感悟记录"""
insight = get_object_or_404(InsightRecord, pk=pk)
if request.method == 'POST':
form = InsightRecordForm(request.POST, request.FILES, instance=insight)
if form.is_valid():
form.save()
logger.info("编辑感悟记录")
return redirect('yesterday_records')
else:
form = InsightRecordForm(instance=insight)
context = {'form': form, 'insight': insight}
return render(request, 'core/edit_insight.html', context)
# 删除感悟记录
def delete_insight(request, pk):
"""删除感悟记录"""
insight = get_object_or_404(InsightRecord, pk=pk)
if request.method == 'POST':
insight.delete()
logger.info("删除感悟记录")
return redirect('yesterday_records')
context = {'insight': insight}
return render(request, 'core/delete_insight.html', context)
# 家庭事项视图
def family_tasks(request):
"""家庭事项"""
logger.info("用户访问家庭事项页面")
tasks = FamilyTask.objects.all()
context = {
'tasks': tasks,
}
return render(request, 'core/family_tasks.html', context)
# 添加家庭事项
def add_family_task(request):
"""添加家庭事项"""
if request.method == 'POST':
form = FamilyTaskForm(request.POST)
if form.is_valid():
form.save()
logger.info(f"添加家庭事项: {form.cleaned_data['content'][:20]}...")
return redirect('family_tasks')
else:
form = FamilyTaskForm()
context = {'form': form}
return render(request, 'core/add_family_task.html', context)
# 编辑家庭事项
def edit_family_task(request, pk):
"""编辑家庭事项"""
task = get_object_or_404(FamilyTask, pk=pk)
if request.method == 'POST':
form = FamilyTaskForm(request.POST, instance=task)
if form.is_valid():
form.save()
logger.info(f"编辑家庭事项: {form.cleaned_data['content'][:20]}...")
return redirect('family_tasks')
else:
form = FamilyTaskForm(instance=task)
context = {'form': form, 'task': task}
return render(request, 'core/edit_family_task.html', context)
# 删除家庭事项
def delete_family_task(request, pk):
"""删除家庭事项"""
task = get_object_or_404(FamilyTask, pk=pk)
if request.method == 'POST':
task.delete()
logger.info(f"删除家庭事项: {task.content[:20]}...")
return redirect('family_tasks')
context = {'task': task}
return render(request, 'core/delete_family_task.html', context)
# 今日计划视图
def today_plan(request):
"""今日计划"""
logger.info("用户访问今日计划页面")
today = timezone.now().date()
# 获取今日计划
plans = TodayPlan.objects.filter(date=today)
context = {
'today': today,
'plans': plans,
}
return render(request, 'core/today_plan.html', context)
# 添加今日计划
def add_today_plan(request):
"""添加今日计划"""
if request.method == 'POST':
form = TodayPlanForm(request.POST)
if form.is_valid():
form.save()
logger.info(f"添加今日计划: {form.cleaned_data['content'][:20]}...")
return redirect('today_plan')
else:
form = TodayPlanForm()
context = {'form': form}
return render(request, 'core/add_today_plan.html', context)
# 编辑今日计划
def edit_today_plan(request, pk):
"""编辑今日计划"""
plan = get_object_or_404(TodayPlan, pk=pk)
if request.method == 'POST':
form = TodayPlanForm(request.POST, instance=plan)
if form.is_valid():
form.save()
logger.info(f"编辑今日计划: {form.cleaned_data['content'][:20]}...")
return redirect('today_plan')
else:
form = TodayPlanForm(instance=plan)
context = {'form': form, 'plan': plan}
return render(request, 'core/edit_today_plan.html', context)
# 删除今日计划
def delete_today_plan(request, pk):
"""删除今日计划"""
plan = get_object_or_404(TodayPlan, pk=pk)
if request.method == 'POST':
plan.delete()
logger.info(f"删除今日计划: {plan.content[:20]}...")
return redirect('today_plan')
context = {'plan': plan}
return render(request, 'core/delete_today_plan.html', context)
# 切换今日计划状态
def toggle_today_plan(request, pk):
"""切换今日计划状态"""
plan = get_object_or_404(TodayPlan, pk=pk)
pending_status = Status.objects.get(name='pending')
completed_status = Status.objects.get(name='completed')
plan.status = completed_status if plan.status == pending_status else pending_status
plan.save()
logger.info(f"切换今日计划状态: {plan.content[:20]}... -> {plan.get_status_display()}")
if request.headers.get('x-requested-with') == 'XMLHttpRequest':
return JsonResponse({'status': plan.status, 'status_text': plan.get_status_display()})
return redirect('today_plan')
# 生成报告
def generate_report(request):
"""生成报告"""
logger.info("用户访问报告生成页面")
today = timezone.now().date()
yesterday = today - timedelta(days=1)
# 获取昨日记录
yesterday_reading = ReadingRecord.objects.filter(date=yesterday)
yesterday_insight = InsightRecord.objects.filter(date=yesterday)
# 获取今日计划
today_plan = TodayPlan.objects.filter(date=today)
# 获取家庭事项统计
family_task_stats = FamilyTask.objects.values('type').annotate(count=Count('id'))
context = {
'today': today,
'yesterday': yesterday,
'yesterday_reading': yesterday_reading,
'yesterday_insight': yesterday_insight,
'today_plan': today_plan,
'family_task_stats': family_task_stats,
}
return render(request, 'core/report.html', context)
# 查看报告
def view_report(request, date):
"""查看指定日期的报告"""
logger.info(f"用户查看报告: {date}")
report_date = datetime.strptime(date, '%Y-%m-%d').date()
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)
# 获取家庭事项统计
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,
}
return render(request, 'core/report.html', context)
# 生成PDF报告
def generate_pdf_report(request, date):
"""生成PDF报告"""
if not is_weasyprint_available():
logger.error("WeasyPrint库不可用无法生成PDF报告")
return HttpResponse("PDF功能不可用请检查WeasyPrint库是否正确安装", status=500)
logger.info(f"用户生成PDF报告: {date}")
report_date = datetime.strptime(date, '%Y-%m-%d').date()
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)
# 获取家庭事项统计
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(request, 'core/report_pdf.html', context).content.decode('utf-8')
# 生成PDF
pdf_file = f"report_{date}.pdf"
pdf_path = os.path.join(settings.REPORTS_ROOT, pdf_file)
# 确保报告目录存在
os.makedirs(settings.REPORTS_ROOT, exist_ok=True)
# 动态导入WeasyPrint
from weasyprint import HTML
HTML(string=html_string).write_pdf(pdf_path)
logger.info(f"PDF报告生成成功: {pdf_path}")
# 返回PDF文件
with open(pdf_path, 'rb') as f:
response = HttpResponse(f.read(), content_type='application/pdf')
response['Content-Disposition'] = f'attachment; filename="{pdf_file}"'
return response
# 系统配置
def system_settings(request):
"""系统配置"""
logger.info("用户访问系统配置页面")
config = SystemConfig.get_config()
if request.method == 'POST':
form = SystemConfigForm(request.POST, instance=config)
if form.is_valid():
form.save()
logger.info("系统配置更新成功")
return redirect('system_settings')
else:
form = SystemConfigForm(instance=config)
context = {'form': form}
return render(request, 'core/system_settings.html', context)
# 发送邮件
def send_email_view(request):
"""手动发送邮件"""
if not is_weasyprint_available():
logger.error("WeasyPrint库不可用无法生成PDF报告")
return HttpResponse("PDF功能不可用无法发送邮件", status=500)
logger.info("用户手动发送邮件")
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 redirect('system_settings')
# 生成PDF报告
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)
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(request, '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)
# 动态导入WeasyPrint
from weasyprint import HTML
HTML(string=html_string).write_pdf(pdf_path)
# 发送邮件
subject = f"家庭日报 - {today_str}"
message = f"这是您的家庭日报,日期:{today_str}"
from_email = config.smtp_username
recipient_list = [config.recipient_email]
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')
# 发送邮件
try:
email.send()
logger.info(f"邮件发送成功,收件人:{config.recipient_email}")
return redirect('index')
except Exception as e:
logger.error(f"邮件发送失败:{str(e)}")
return redirect('system_settings')
# 别名保持URL配置一致
def send_email(request):
"""发送邮件别名"""
return send_email_view(request)