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

如何基于StudyYear模型的日期范围生成含每月记录的QuerySet?

解决方案:生成学年日期范围内的月度记录

以下提供两种实现方案,根据你的数据量和数据库类型选择:

方案一:Python层面处理(通用所有数据库,适合小数据量)

遍历每个StudyYear实例,逐个生成日期范围内的月度记录,附加code和name字段:

from datetime import datetime

def generate_monthly_study_records(study_year_queryset):
    monthly_records = []
    for study_year in study_year_queryset:
        # 初始化起始月份的第一天
        current_month = datetime(study_year.date_begin.year, study_year.date_begin.month, 1).date()
        # 计算结束月份的第一天
        end_month = datetime(study_year.date_end.year, study_year.date_end.month, 1).date()
        
        while current_month <= end_month:
            # 生成code和name字段
            code = f"{current_month.month}_{current_month.year}"
            name = current_month.strftime("%B %Y")
            
            # 构造包含原字段与新字段的记录
            record = {
                "id": study_year.id,
                "date_begin": study_year.date_begin,
                "date_end": study_year.date_end,
                "code": code,
                "name": name
            }
            monthly_records.append(record)
            
            # 切换到下一个月
            if current_month.month == 12:
                current_month = datetime(current_month.year + 1, 1, 1).date()
            else:
                current_month = datetime(current_month.year, current_month.month + 1, 1).date()
    
    return monthly_records

使用示例

# 获取目标QuerySet
target_years = StudyYear.objects.filter(id=1)
# 生成月度记录
monthly_data = generate_monthly_study_records(target_years)

如果需要更结构化的返回值,可以用dataclass包装:

from dataclasses import dataclass
from datetime import date

@dataclass
class MonthlyStudyYear:
    id: int
    date_begin: date
    date_end: date
    code: str
    name: str

# 在生成记录时替换为:
monthly_records.append(MonthlyStudyYear(**record))

方案二:数据库层面生成(仅PostgreSQL,适合大数据量)

利用PostgreSQL的generate_series函数直接在数据库生成月度序列,效率更高:

from django.db import models
from django.db.models import F, Func, Value, CharField
from django.db.models.functions import Concat, ExtractMonth, ExtractYear, TruncMonth

monthly_queryset = StudyYear.objects.annotate(
    # 截断到起止月份的第一天
    start_month=TruncMonth('date_begin'),
    end_month=TruncMonth('date_end')
).annotate(
    # 生成日期范围内的所有月份
    month=Func(
        F('start_month'),
        F('end_month'),
        Value('1 month'),
        function='generate_series',
        output_field=models.DateField()
    )
).annotate(
    # 生成code字段:月份_年份
    code=Concat(
        ExtractMonth('month'),
        Value('_'),
        ExtractYear('month'),
        output_field=CharField()
    ),
    # 生成name字段:英文月份名 年份
    name=Func(
        F('month'),
        Value('FMMonth YYYY'),
        function='to_char',
        output_field=CharField()
    )
).values('id', 'date_begin', 'date_end', 'code', 'name')

说明

  • 返回的是ValuesQuerySet,支持Django ORM的链式操作(如filter、order_by)
  • 如果使用MySQL,没有generate_series函数,建议采用方案一

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 13:01:18