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

Django实现指定年份月份天数自动计算(含闰年2月29天)

Django模型修正:自动计算月份天数(含闰年处理)

原代码存在的问题

  • get_day_count 方法逻辑完全错误:错误查询所有MainMonth对象,过滤条件无效,没有正确关联当前月份所属的年份
  • 未利用外键直接关联的MainYear实例,做了多余的无效查询
  • 没实现通过save方法自动将计算结果保存到day_count字段,无法持久化数据

修正方案

以下是完整的修正代码,核心是在MainMonth的save方法中自动计算天数,同时处理闰年场景:

import calendar
from django.db import models
from django.urls import reverse
from django.core.validators import MaxValueValidator

# 假设get_current_year是你定义的获取当前年份的函数
def get_current_year():
    return str(calendar.datetime.datetime.now().year)

class MainYear(models.Model):
    year = models.CharField(max_length=4, blank=True, null=True, default=get_current_year)
    # 修正default:原代码用get_current_year()会在模型加载时执行一次,改成不带括号,每次创建实例时才调用

    def __str__(self):
        return str(self.year)

    @property
    def get_all_month(self):
        # 对应MainMonth的related_name,后面改成了"months"
        return self.months.all()

    def get_absolute_url(self):
        return reverse("agenda:ajax_month", kwargs={"pk": self.id})
   
class MainMonth(models.Model):
    # 修正related_name,避免和模型名冲突,改成语义化的"months"
    main_year = models.ForeignKey(MainYear, on_delete=models.CASCADE, blank=True, null=True, related_name="months")
    month = models.PositiveSmallIntegerField(validators=[MaxValueValidator(12)], default=1, blank=True, null=True)
    day_count = models.PositiveSmallIntegerField(validators=[MaxValueValidator(31)], blank=True, null=True)

    def __str__(self):
        return str(self.month)
    
    def save(self, *args, **kwargs):
        # 只有关联年份和月份都存在时,才计算天数
        if self.main_year and self.main_year.year and self.month:
            try:
                year_int = int(self.main_year.year)
                month_int = int(self.month)
                # 用calendar.monthrange自动处理闰年,返回该月天数
                _, days = calendar.monthrange(year_int, month_int)
                self.day_count = days
            except (ValueError, TypeError):
                # 年份或月份格式无效时,跳过赋值
                pass
        super().save(*args, **kwargs)
    
    # 可选:保留只读属性,支持实时获取天数(未保存时也能计算)
    @property
    def get_day_count(self):
        if not self.day_count and self.main_year and self.main_year.year and self.month:
            try:
                year_int = int(self.main_year.year)
                month_int = int(self.month)
                _, days = calendar.monthrange(year_int, month_int)
                return days
            except (ValueError, TypeError):
                return None
        return self.day_count

关键修改说明

  1. 修复默认年份逻辑:原default=get_current_year()会在模型加载时固定年份,改成default=get_current_year后,每次创建实例都会获取最新年份。
  2. 优化外键反向关联:把related_name改成"months",避免和模型名冲突,MainYear实例可以通过instance.months.all()直接查询关联月份。
  3. 自动计算并保存天数:重写save方法,利用calendar.monthrange自动判断闰年,计算对应月份的天数并赋值给day_count,保存时自动持久化到数据库。
  4. 异常容错:捕获年份/月份格式错误的异常,避免保存失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 15:55:19