Django如何对模型两个DecimalField求和并在admin视图展示
Django Admin 展示两个DecimalField求和结果方案
之前实现不生效的核心原因有两个:
- 自定义的求和方法没有配置到Admin的列表展示规则里,Admin不会自动拉取模型自定义方法的返回值渲染
- 额外新增的
total_price是独立的数据库字段,没有绑定自动赋值逻辑,会一直显示默认值0,属于冗余字段,纯展示场景完全不需要落库存储。
正确实现方式(无冗余字段,动态计算)
1. 调整模型层代码
删掉多余的total_price数据库字段,保留两个业务字段,补充求和方法的展示描述:
from django.db import models class YourBusinessModel(models.Model): price = models.DecimalField(max_digits=6, decimal_places=2) spotters = models.DecimalField(max_digits=6, decimal_places=2, default=150) def get_total_cost(self): # 直接返回两个字段的和,Decimal类型相加不会丢失精度 return self.price + self.spotters # 配置Admin列表里该列的表头文字 get_total_cost.short_description = "总价"
2. 配置Admin类
在对应app的admin.py里,把自定义的求和方法加入list_display列表,配置后Admin列表页就会渲染该列:
from django.contrib import admin from django.db.models import F from .models import YourBusinessModel @admin.register(YourBusinessModel) class YourBusinessModelAdmin(admin.ModelAdmin): # 列表页展示的字段,把自定义方法名加进去即可 list_display = ("id", "price", "spotters", "get_total_cost") # 可选配置:支持点击总价表头排序 def get_queryset(self, request): queryset = super().get_queryset(request) # 用ORM的F表达式提前注解求和结果,用于排序 return queryset.annotate(_total_val=F("price") + F("spotters")) def get_total_cost(self, obj): return obj._total_val # 绑定排序用的注解字段 get_total_cost.admin_order_field = "_total_val" get_total_cost.short_description = "总价"
特殊场景:需要把总价持久化到数据库
如果有检索、索引需求,必须把总价存在数据库里,才保留total_price字段,此时需要重写模型的save方法,每次保存实例时自动计算赋值,避免数据不一致:
from django.db import models class YourBusinessModel(models.Model): price = models.DecimalField(max_digits=6, decimal_places=2) spotters = models.DecimalField(max_digits=6, decimal_places=2, default=150) total_price = models.DecimalField(max_digits=10, decimal_places=2, default=0) def save(self, *args, **kwargs): # 保存前先计算总价赋值 self.total_price = self.price + self.spotters super().save(*args, **kwargs)
这种方式配置Admin时,直接把total_price加入list_display即可,注意用QuerySet.update()批量更新数据时不会触发save方法,需要手动同步总价字段值,非必要不推荐用这种方案。
内容的提问来源于stack exchange,提问作者Rp_Web
相关产品推荐
相关产品推荐

