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

如何在Django中跨多日追踪用户学习时长并按周重置?

解决方案

1. 调整Django数据模型

原有的totallearningtime字段仅能存储累计总时长,无法按天拆分记录。需要新增每日学习时长模型,用来追踪用户每天的学习时间:

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone

class DailyLearningTime(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='daily_learning_times')
    date = models.DateField(default=timezone.now)
    daily_duration = models.DecimalField(default=0, decimal_places=2, max_digits=10)  # 当天学习时长,单位可根据需求调整为分钟/小时

    class Meta:
        unique_together = ('user', 'date')  # 确保用户每天仅存一条记录

原有的totallearningtime字段可保留用于累计总时长统计,也可通过DailyLearningTime的记录总和计算,按需选择。

2. 实现每日时长更新逻辑

当用户产生学习行为时,调用以下逻辑更新对应日期的学习时长:

def update_daily_learning_time(user, add_duration):
    today = timezone.now().date()
    # 获取或创建当天的学习记录
    daily_record, created = DailyLearningTime.objects.get_or_create(user=user, date=today)
    daily_record.daily_duration += add_duration
    daily_record.save()

    # 可选:同步更新用户总学习时长
    user.profile.totallearningtime += add_duration  # 假设总时长存储在User关联的Profile模型中
    user.profile.save()

3. 后端接口:获取当前周学习数据

编写视图接口,返回当前用户本周(周一至周日)的每日学习时长,格式适配Chart.js:

from django.http import JsonResponse
from django.utils import timezone
from datetime import timedelta

def weekly_learning_data(request):
    if not request.user.is_authenticated:
        return JsonResponse({'error': '未登录'}, status=401)
    
    user = request.user
    # 计算本周一的日期(weekday()返回0=周一,6=周日)
    today = timezone.now().date()
    start_of_week = today - timedelta(days=today.weekday())
    end_of_week = start_of_week + timedelta(days=6)

    # 查询本周所有学习记录
    weekly_records = DailyLearningTime.objects.filter(
        user=user,
        date__gte=start_of_week,
        date__lte=end_of_week
    ).values('date', 'daily_duration')

    # 构建周一到周日的完整数据,缺失日期填充0
    week_days = [start_of_week + timedelta(days=i) for i in range(7)]
    day_labels = ['Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun']
    daily_data = []

    for day in week_days:
        record = next((r for r in weekly_records if r['date'] == day), None)
        daily_data.append(float(record['daily_duration']) if record else 0)

    return JsonResponse({
        'labels': day_labels,
        'data': daily_data,
        'total_weekly_time': sum(daily_data)  # 可选:返回本周总时长
    })

在urls.py中配置接口路由:

from django.urls import path
from .views import weekly_learning_data

urlpatterns = [
    # ... 其他路由
    path('api/weekly-learning-data/', weekly_learning_data, name='weekly_learning_data'),
]

4. 修改前端Chart.js代码,动态加载数据

替换静态占位数据,通过AJAX请求后端接口获取本周数据:

<canvas id="myChart"></canvas>

<script>
const ctx = document.getElementById("myChart");

// 从后端获取每周学习数据
fetch('/api/weekly-learning-data/')
    .then(response => response.json())
    .then(data => {
        new Chart(ctx, {
            type: "line",
            data: {
                labels: data.labels,
                datasets: [
                    {
                        label: "Learning Time",
                        data: data.data,
                        fill: false,
                        cubicInterpolationMode: "monotone",
                        tension: 0.4,
                        borderColor: '#ff6384'  // 自定义线条颜色
                    },
                ],
            },
            options: {
                responsive: true,
                maintainAspectRatio: true,
                plugins: {
                    title: {
                        display: true,
                        text: `Total Time: ${Math.floor(data.total_weekly_time/60)}h ${Math.round(data.total_weekly_time%60)}m`  // 格式化总时长显示
                    },
                },
                interaction: {
                    intersect: false,
                },
                scales: {
                    x: {
                        display: true,
                        title: {
                            display: true,
                            text: 'Week Days'
                        },
                    },
                    y: {
                        display: true,
                        title: {
                            display: true,
                            text: "Minutes",  // 与后端数据单位保持一致,可改为Hours
                        },
                        suggestedMin: 0,
                        suggestedMax: 200,
                    },
                },
            },
        });
    })
    .catch(error => console.error('获取数据失败:', error));
</script>

关键说明

  • 每周重置逻辑:无需手动重置数据,后端接口每次仅查询当前自然周的记录,自动实现“每周从零开始统计”的效果,同时保留历史周数据。
  • 时区处理:确保Djangosettings.py中TIME_ZONE配置正确,避免日期计算偏差。
  • 单位统一:注意daily_duration的单位(分钟/小时),前端图表Y轴标签需与之对应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 18:31:09