Django中根据布尔字段状态自动增减sanction_sn的实现需求
审批记录sanction_sn自动维护方案
修正后的模型定义
首先修正原模型中的拼写错误(Models.model改为models.Model):
from django.db import models class Application_data(models.Model): application_sn = models.AutoField(primary_key=True) applicant_name = models.CharField(max_length=20) sanction_sn = models.IntegerField(default=0) is_sanctioned = models.BooleanField(default=False)
核心逻辑实现
通过Django的信号机制,在记录保存时自动处理sanction_sn的增减逻辑:
from django.db.models.signals import pre_save, post_save from django.dispatch import receiver from django.db.models import F, Max from .models import Application_data # 保存实例修改前的状态,用于后续对比 @receiver(pre_save, sender=Application_data) def save_old_state(sender, instance, **kwargs): if instance.pk: old_instance = sender.objects.get(pk=instance.pk) instance._old_is_sanctioned = old_instance.is_sanctioned instance._old_sanction_sn = old_instance.sanction_sn else: instance._old_is_sanctioned = False instance._old_sanction_sn = 0 # 根据状态变化更新sanction_sn @receiver(post_save, sender=Application_data) def update_sanction_sn(sender, instance, created, **kwargs): # 从不审批转为审批时,生成递增的sanction_sn if not instance._old_is_sanctioned and instance.is_sanctioned: max_sn = sender.objects.filter(is_sanctioned=True).aggregate(Max('sanction_sn'))['sanction_sn__max'] new_sn = max_sn + 1 if max_sn else 1 sender.objects.filter(pk=instance.pk).update(sanction_sn=new_sn) # 从审批转为不审批时,递减后续已审批记录的sanction_sn elif instance._old_is_sanctioned and not instance.is_sanctioned: old_sn = instance._old_sanction_sn sender.objects.filter(is_sanctioned=True, sanction_sn__gt=old_sn).update(sanction_sn=F('sanction_sn') - 1) sender.objects.filter(pk=instance.pk).update(sanction_sn=0)
关键说明
- 信号加载:需确保信号在项目启动时被加载,可在app的
apps.py文件的ready()方法中导入信号模块,或直接在models.py末尾导入。 - 并发安全:使用
F()表达式进行批量更新,避免多线程操作时的数据不一致问题。 - 需求匹配:
- 审批新记录时,自动取当前最大已审批
sanction_sn加1,保证递增连续性。 - 取消某条已审批记录时,仅将
sanction_sn大于该记录原数值的已审批记录统一减1,不影响前面的记录,完全符合示例场景。
- 审批新记录时,自动取当前最大已审批
内容的提问来源于stack exchange,提问作者Kme
相关产品推荐
相关产品推荐

