Files
diary-family/core/views.py
xiaji f7692a6db6 feat(views): 为所有视图添加登录验证装饰器
为保护用户数据安全,防止未授权访问,在所有需要用户认证的视图函数上添加@login_required装饰器
2026-01-28 21:39:41 +08:00

927 lines
32 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 django.views.decorators.csrf import csrf_exempt
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib import messages
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是否真正可用检查依赖库
test_html = HTML(string="<html><body>Test</body></html>")
# 尝试生成PDF以验证依赖库是否可用
import tempfile
with tempfile.NamedTemporaryFile(suffix='.pdf', delete=True) as tmp:
test_html.write_pdf(tmp.name)
WEASYPRINT_AVAILABLE = True
logger.info("WeasyPrint库可用PDF功能正常")
except ImportError:
logger.warning("WeasyPrint库无法导入PDF功能将不可用")
WEASYPRINT_AVAILABLE = False
except Exception as e:
logger.warning(f"WeasyPrint依赖库不可用: {str(e)}PDF功能将不可用")
WEASYPRINT_AVAILABLE = False
return WEASYPRINT_AVAILABLE
from .models import (
ReadingRecord,
InsightRecord,
Summary,
FamilyTask,
TodayPlan,
SystemConfig,
FamilyMember,
SummaryCategory
)
from .forms import (
ReadingRecordForm,
InsightRecordForm,
SummaryForm,
FamilyTaskForm,
TodayPlanForm,
SystemConfigForm
)
# 首页视图
@login_required
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)
# 昨日记录视图
@login_required
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)
# 添加阅读记录
@login_required
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)
# 编辑阅读记录
@login_required
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)
# 删除阅读记录
@login_required
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)
# 添加感悟记录
@login_required
def add_insight(request):
"""添加感悟记录"""
family_members = FamilyMember.objects.all()
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, 'family_members': family_members}
return render(request, 'core/add_insight.html', context)
# 编辑感悟记录
@login_required
def edit_insight(request, pk):
"""编辑感悟记录"""
insight = get_object_or_404(InsightRecord, pk=pk)
family_members = FamilyMember.objects.all()
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, 'family_members': family_members}
return render(request, 'core/edit_insight.html', context)
# 删除感悟记录
@login_required
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)
# 今日记录视图
@login_required
def today_records(request):
"""今日记录"""
logger.info("用户访问今日记录页面")
today = timezone.now().date()
# 获取今日阅读记录
reading_records = ReadingRecord.objects.filter(date=today)
# 获取今日感悟记录
insight_records = InsightRecord.objects.filter(date=today)
context = {
'today': today,
'reading_records': reading_records,
'insight_records': insight_records,
}
return render(request, 'core/today_records.html', context)
@login_required
# 添加今日阅读记录
def add_today_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()
reading.save()
logger.info(f"添加今日阅读记录: {form.cleaned_data['title']}")
return redirect('today_records')
else:
form = ReadingRecordForm()
context = {'form': form}
return render(request, 'core/add_reading.html', context)
# 编辑今日阅读记录
def edit_today_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('today_records')
else:
form = ReadingRecordForm(instance=reading)
context = {'form': form, 'reading': reading}
return render(request, 'core/edit_reading.html', context)
# 删除今日阅读记录
def delete_today_reading(request, pk):
"""删除今日阅读记录"""
reading = get_object_or_404(ReadingRecord, pk=pk)
if request.method == 'POST':
reading.delete()
logger.info(f"删除今日阅读记录: {reading.title}")
return redirect('today_records')
context = {'reading': reading}
return render(request, 'core/delete_reading.html', context)
# 添加今日感悟记录
@login_required
def add_today_insight(request):
"""添加今日感悟记录"""
family_members = FamilyMember.objects.all()
if request.method == 'POST':
form = InsightRecordForm(request.POST, request.FILES)
if form.is_valid():
insight = form.save(commit=False)
insight.date = timezone.now().date()
insight.save()
logger.info("添加今日感悟记录")
return redirect('today_records')
else:
form = InsightRecordForm()
context = {'form': form, 'family_members': family_members}
return render(request, 'core/add_insight.html', context)
# 编辑今日感悟记录
def edit_today_insight(request, pk):
"""编辑今日感悟记录"""
insight = get_object_or_404(InsightRecord, pk=pk)
family_members = FamilyMember.objects.all()
if request.method == 'POST':
form = InsightRecordForm(request.POST, request.FILES, instance=insight)
if form.is_valid():
form.save()
logger.info("编辑今日感悟记录")
return redirect('today_records')
else:
form = InsightRecordForm(instance=insight)
context = {'form': form, 'insight': insight, 'family_members': family_members}
return render(request, 'core/edit_insight.html', context)
# 删除今日感悟记录
def delete_today_insight(request, pk):
"""删除今日感悟记录"""
insight = get_object_or_404(InsightRecord, pk=pk)
if request.method == 'POST':
insight.delete()
logger.info("删除今日感悟记录")
return redirect('today_records')
context = {'insight': insight}
return render(request, 'core/delete_insight.html', context)
# 汇总记录视图
def summaries(request):
"""汇总记录"""
logger.info("用户访问汇总记录页面")
today = timezone.now().date()
yesterday = today - timedelta(days=1)
summary_records = Summary.objects.filter(date=yesterday)
context = {
'yesterday': yesterday,
'summary_records': summary_records,
}
return render(request, 'core/summaries.html', context)
# 添加汇总记录
def add_summary(request):
"""添加汇总记录"""
family_members = FamilyMember.objects.all()
categories = SummaryCategory.objects.all()
if request.method == 'POST':
form = SummaryForm(request.POST, request.FILES)
if form.is_valid():
form.save()
logger.info(f"添加汇总记录: {form.cleaned_data['content'][:20]}...")
return redirect('summaries')
else:
form = SummaryForm()
context = {'form': form, 'family_members': family_members, 'categories': categories}
return render(request, 'core/add_summary.html', context)
# 编辑汇总记录
@login_required
def edit_summary(request, pk):
"""编辑汇总记录"""
summary = get_object_or_404(Summary, pk=pk)
family_members = FamilyMember.objects.all()
categories = SummaryCategory.objects.all()
if request.method == 'POST':
form = SummaryForm(request.POST, request.FILES, instance=summary)
if form.is_valid():
form.save()
logger.info(f"编辑汇总记录: {form.cleaned_data['content'][:20]}...")
return redirect('summaries')
else:
form = SummaryForm(instance=summary)
context = {'form': form, 'summary': summary, 'family_members': family_members, 'categories': categories}
return render(request, 'core/edit_summary.html', context)
# 删除汇总记录
@login_required
def delete_summary(request, pk):
"""删除汇总记录"""
summary = get_object_or_404(Summary, pk=pk)
if request.method == 'POST':
summary.delete()
logger.info(f"删除汇总记录: {summary.content[:20]}...")
return redirect('summaries')
context = {'summary': summary}
return render(request, 'core/delete_summary.html', context)
# 家庭事项视图
@login_required
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)
# 删除家庭事项
@login_required
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)
# 添加今日计划
@login_required
def add_today_plan(request):
"""添加今日计划"""
family_members = FamilyMember.objects.all()
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, 'family_members': family_members}
return render(request, 'core/add_today_plan.html', context)
# 编辑今日计划
def edit_today_plan(request, pk):
"""编辑今日计划"""
plan = get_object_or_404(TodayPlan, pk=pk)
family_members = FamilyMember.objects.all()
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, 'family_members': family_members}
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)
# 切换今日计划状态
@login_required
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')
# 生成报告
@login_required
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)
yesterday_summary = Summary.objects.filter(date=yesterday)
# 获取今日计划
today_plan = TodayPlan.objects.filter(date=today)
# 获取家庭事项统计
family_task_stats = FamilyTask.objects.values('type').annotate(count=Count('id'))
# 获取最近7天的日期列表用于生成历史PDF链接
historical_dates = []
for i in range(1, 8):
historical_date = today - timedelta(days=i)
historical_dates.append(historical_date)
# 检查是否有更早的PDF文件
has_earlier_pdfs = False
seven_days_ago = today - timedelta(days=7)
pdf_files = [f for f in os.listdir(settings.REPORTS_ROOT) if f.endswith('.pdf')]
for pdf_file in pdf_files:
try:
# 从文件名中提取日期
date_str = pdf_file.replace('report_', '').replace('.pdf', '')
file_date = datetime.strptime(date_str, '%Y-%m-%d').date()
if file_date < seven_days_ago:
has_earlier_pdfs = True
break
except Exception:
continue
context = {
'today': today,
'yesterday': yesterday,
'yesterday_reading': yesterday_reading,
'yesterday_insight': yesterday_insight,
'yesterday_summary': yesterday_summary,
'today_plan': today_plan,
'family_task_stats': family_task_stats,
'historical_dates': historical_dates,
'has_earlier_pdfs': has_earlier_pdfs,
}
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)
yesterday_summary = Summary.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,
'yesterday_summary': yesterday_summary,
'today_plan': today_plan,
'family_task_stats': family_task_stats,
}
return render(request, 'core/report.html', context)
# 生成PDF报告
@login_required
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}")
try:
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)
yesterday_summary = Summary.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,
'yesterday_summary': yesterday_summary,
'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
except Exception as e:
logger.error(f"生成PDF报告失败: {str(e)}")
return HttpResponse(f"生成PDF报告失败: {str(e)}", status=500)
# 预览PDF报告
def preview_pdf_report(request, date):
"""预览PDF报告HTML格式样式与PDF一致"""
logger.info(f"用户预览PDF报告: {date}")
try:
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)
yesterday_summary = Summary.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,
'yesterday_summary': yesterday_summary,
'today_plan': today_plan,
'family_task_stats': family_task_stats,
}
# 渲染HTML模板与PDF使用相同的模板
return render(request, 'core/report_pdf.html', context)
except Exception as e:
logger.error(f"预览PDF报告失败: {str(e)}")
return HttpResponse(f"预览PDF报告失败: {str(e)}", status=500)
# 系统配置
@login_required
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)
yesterday_summary = Summary.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,
'yesterday_summary': yesterday_summary,
'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)
# PDF文件列表
@login_required
def pdf_list(request):
"""显示服务器上已有的PDF文件列表"""
logger.info("用户访问PDF文件列表页面")
# 获取所有PDF文件
pdf_files = [f for f in os.listdir(settings.REPORTS_ROOT) if f.endswith('.pdf')]
# 解析文件名,提取日期,并按日期降序排序
pdf_info = []
for pdf_file in pdf_files:
try:
# 从文件名中提取日期
date_str = pdf_file.replace('report_', '').replace('.pdf', '')
file_date = datetime.strptime(date_str, '%Y-%m-%d').date()
pdf_info.append({
'filename': pdf_file,
'date': file_date,
'date_str': date_str
})
except Exception as e:
logger.error(f"解析PDF文件名失败: {pdf_file}, 错误: {str(e)}")
continue
# 按日期降序排序
pdf_info.sort(key=lambda x: x['date'], reverse=True)
context = {
'pdf_files': pdf_info
}
return render(request, 'core/pdf_list.html', context)
def api_submit_summary(request):
"""API提交汇总记录 - 仅接受指定分类和发言人的记录"""
logger.info("API: 收到汇总记录提交请求")
if request.method != 'POST':
return JsonResponse({'success': False, 'message': '只支持POST请求'}, status=405)
try:
content = request.POST.get('content', '').strip()
if not content:
return JsonResponse({'success': False, 'message': '内容不能为空'}, status=400)
category_name = "定期"
speaker_name = "机器人"
try:
category = SummaryCategory.objects.get(name=category_name)
except SummaryCategory.DoesNotExist:
logger.error(f"API: 分类 '{category_name}' 不存在")
return JsonResponse({'success': False, 'message': f"分类 '{category_name}' 不存在"}, status=400)
try:
speaker = FamilyMember.objects.get(name=speaker_name)
except FamilyMember.DoesNotExist:
logger.error(f"API: 发言人 '{speaker_name}' 不存在")
return JsonResponse({'success': False, 'message': f"发言人 '{speaker_name}' 不存在"}, status=400)
# 获取来源,支持客户端提交
source = request.POST.get('source', '').strip()
if not source:
source = ""
# 如果没有提供来源,自动生成
if not source:
import socket
hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)
source = f"{hostname} ({local_ip})"
summary = Summary.objects.create(
date=timezone.now().date(),
category=category,
speaker=speaker,
content=content,
source=source
)
logger.info(f"API: 汇总记录创建成功ID={summary.id}")
return JsonResponse({
'success': True,
'message': '提交成功',
'id': summary.id
})
except Exception as e:
logger.error(f"API: 提交汇总记录失败: {str(e)}")
return JsonResponse({'success': False, 'message': f"提交失败: {str(e)}"}, status=500)
# 登录视图
def user_login(request):
"""用户登录"""
if request.user.is_authenticated:
logger.info(f"用户 {request.user.username} 已登录,重定向到首页")
return redirect('index')
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
logger.info(f"用户登录尝试: {username}")
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
logger.info(f"用户 {username} 登录成功")
messages.success(request, '登录成功!')
return redirect('index')
else:
logger.warning(f"用户 {username} 登录失败: 用户名或密码错误")
messages.error(request, '用户名或密码错误,请重新尝试。')
return render(request, 'core/login.html')
# 注销视图
def user_logout(request):
"""用户注销"""
if request.user.is_authenticated:
logger.info(f"用户 {request.user.username} 注销")
logout(request)
messages.success(request, '已成功注销!')
return redirect('login')