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

Django实现:为ServiceEvent添加关联Part的总价存储字段

给ServiceEvent添加自动维护的total_price字段方案

要实现service_event_obj.total_price直接获取关联Part的总价,同时保证字段值自动更新,按以下步骤操作:

1. 修改Model,新增total_price字段

在ServiceEvent类中添加total_price字段,类型和Part的price保持一致,默认值设为0(确保空事件总价为0):

class ServiceEvent(Model):
    date = DateTimeField(null=False, blank=False, db_column='date', 
                         default=datetime.now())
    vehicle = ForeignKey(Vehicle, on_delete=models.CASCADE)
    description = TextField(null=True, blank=False, db_column='description')
    
    # The contents of the notifications to create for this event.
    notification_contents = TextField(null=True, blank=False, 
                                      db_column='notification_contents')
    
    # The mileage the event should occur.
    target_mileage = DecimalField(max_digits=10, decimal_places=2, 
                                  null=True, blank=False, 
                                  db_column='target_mileage')
    
    # The mileage at the time of the event.
    event_mileage = DecimalField(max_digits=10, decimal_places=2, 
                                 null=True, blank=False, 
                                 db_column='event_mileage')
    
    # 新增:关联Part的总价
    total_price = DecimalField(max_digits=10, decimal_places=2, null=False, 
                               default=0, db_column='total_price')

class Part(Model):
    part_number = CharField(max_length=100, null=False, blank=False, 
                            db_column='part_number')
    description = CharField(max_length=100, null=False, blank=False, 
                            db_column='description')
    price = DecimalField(max_digits=10, decimal_places=2, null=False, 
                         db_column='price')
    service_event = ForeignKey(ServiceEvent, on_delete=models.CASCADE)

2. 用Django信号自动维护总价

当Part新增、修改或删除时,自动更新对应ServiceEvent的total_price。在models.py中添加信号处理逻辑:

from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django.db.models import Sum

@receiver(post_save, sender=Part)
@receiver(post_delete, sender=Part)
def update_service_event_total_price(sender, instance, **kwargs):
    # 计算当前ServiceEvent下所有Part的总价
    total = instance.service_event.part_set.aggregate(total=Sum('price'))['total'] or 0
    # 仅更新total_price字段,提升效率
    instance.service_event.total_price = total
    instance.service_event.save(update_fields=['total_price'])

如果信号单独放在signals.py文件中,需要在apps.py的ready()方法中注册:

from django.apps import AppConfig

class YourAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'your_app_name'

    def ready(self):
        import your_app_name.signals

3. 迁移数据并初始化历史数据

生成并执行迁移文件

运行以下命令创建迁移并更新数据库:

python manage.py makemigrations
python manage.py migrate

初始化已有ServiceEvent的总价

迁移后旧数据的total_price都是默认值0,需要批量计算更新。通过Django Shell执行:

python manage.py shell

在Shell中执行:

from your_app_name.models import ServiceEvent
from django.db.models import Sum

for event in ServiceEvent.objects.all():
    total = event.part_set.aggregate(total=Sum('price'))['total'] or 0
    event.total_price = total
    event.save(update_fields=['total_price'])

效果验证

完成以上步骤后,你就可以直接通过service_event_obj.total_price获取该事件下所有Part的总价,无需每次查询关联Part求和,提升了查询效率。同时,后续对Part的增删改操作都会自动同步更新对应的total_price值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 10:31:33