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

Django中基于单个模型创建多实例?信号实现问题求助

Django模型实例批量创建问题修复

我正尝试在Django中创建模型实例时生成多个实例,最终目标是创建多个实例,但目前先想让信号正常工作。我写的代码无法运行,想要实现创建该模型的副本,原代码如下:

from datetime import datetime, timedelta
import django
from django.conf import settings
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver


class BudgetTransaction(models.Model):
    """
    Individual transaction for Budget
    """

    transaction_types = [
        ('FI', 'Fixed Income'),
        ('FE', 'Fixed Expenses'),
        ('EC', 'Extra Cashflow'),
    ]

    frequencies = [
        ('one', 'one off'),
        ('wk', 'weekly'),
        ('fort', 'fortnightly'),
        ('mon', 'monthly'),
        ('yr', 'yearly'),
        ('day', 'specific day'),
    ]
    today = datetime.today().strftime('%Y-%m-%d')

    owner = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        help_text="Owner of the item"
    )
    transaction_type = models.CharField(max_length=40, choices=transaction_types, default=1)
    transaction_name = models.CharField(max_length=100, null=False)
    transaction_amount = models.IntegerField(null=False)
    next_date = models.DateField(null=False, default=today)
    frequency = models.CharField(max_length=20, choices=frequencies, default=1)
    complete = models.BooleanField(default=False)

    def __str__(self):
        return self.transaction_name

    class Meta:
        ordering = ['next_date']


@receiver(post_save, sender=BudgetTransaction)
def create_forecasted(sender, instance, created, **kwargs):
    if created:
        today = datetime.today()
        this_month = today.month
        months_left = 12 - this_month

        if sender.frequency == "mon":
            BudgetTransaction.objects.create(owner=instance.owner)

核心问题及修复方案

  1. 信号中错误引用sender而非实例
    sender是模型类本身,不是创建的具体实例,判断频率应该用instance.frequency而非sender.frequency。

  2. 创建副本时缺少必填字段
    create方法仅传入owner,但模型中transaction_name、transaction_amount等都是非空字段,需要复制原实例的对应值。

  3. 默认值静态化问题
    类级变量today只会在Django启动时计算一次,不会动态更新当前日期,改用lambda函数动态生成默认日期。

  4. choices默认值不匹配
    transaction_type和frequency的默认值设为1,但choices选项是字符串类型,需对应选项的键值(如'FE'、'one')。


修复后的完整代码

from datetime import datetime, timedelta
from django.conf import settings
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver


class BudgetTransaction(models.Model):
    """
    预算的单个交易记录
    """
    transaction_types = [
        ('FI', '固定收入'),
        ('FE', '固定支出'),
        ('EC', '额外现金流'),
    ]

    frequencies = [
        ('one', '一次性'),
        ('wk', '每周'),
        ('fort', '每两周'),
        ('mon', '每月'),
        ('yr', '每年'),
        ('day', '特定日期'),
    ]

    owner = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        help_text="记录所有者"
    )
    transaction_type = models.CharField(max_length=40, choices=transaction_types, default='FE')
    transaction_name = models.CharField(max_length=100, null=False)
    transaction_amount = models.IntegerField(null=False)
    # 动态获取当前日期,避免启动时固定值
    next_date = models.DateField(null=False, default=lambda: datetime.today().date())
    frequency = models.CharField(max_length=20, choices=frequencies, default='one')
    complete = models.BooleanField(default=False)

    def __str__(self):
        return self.transaction_name

    class Meta:
        ordering = ['next_date']


@receiver(post_save, sender=BudgetTransaction)
def create_forecasted(sender, instance, created, **kwargs):
    if created and instance.frequency == "mon":
        # 生成后续11个月的月度交易实例
        for month_offset in range(1, 12):
            # 计算对应月份的日期(可根据实际需求调整日期计算逻辑)
            next_transaction_date = instance.next_date + timedelta(days=30 * month_offset)
            # 复制原实例字段,创建新实例
            BudgetTransaction.objects.create(
                owner=instance.owner,
                transaction_type=instance.transaction_type,
                transaction_name=instance.transaction_name,
                transaction_amount=instance.transaction_amount,
                next_date=next_transaction_date,
                frequency=instance.frequency,
                complete=instance.complete
            )

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 15:09:12