Django模型@property属性值无法返回问题求助(DRF+Admin场景)
问题原因
你在模型里同时定义了total_inflasi数据库字段和同名的@property计算属性,Django会优先读取数据库字段的值(这里是null),导致你的计算属性根本没被调用,自然在Admin和API里显示不出来。
修复方案
有两种可行的解决思路,根据你的需求选择:
方案1:保留数据库字段,重命名计算属性
如果需要保留数据库里的total_inflasi字段(比如要保留历史数据),把计算属性改名避免冲突:
修改models.py
把@property的名称改成calculated_total_inflasi,同时处理字段为null的情况防止求和报错:
class Inflasi(models.Model): sandang = models.FloatField(null=True) sembako = models.FloatField(null=True) perumahan = models.FloatField(null=True) kesehatan = models.FloatField(null=True) transportasi = models.FloatField(null=True) informasi = models.FloatField(null=True) rekreasi = models.FloatField(null=True) pendidikan = models.FloatField(null=True) penyedia_pangan = models.FloatField(null=True) perawatan_pribadi = models.FloatField(null=True) total_inflasi = models.FloatField(null=True) # 保留数据库字段 tanggal = models.DateField(null=True) @property def calculated_total_inflasi(self): fields = [ self.sandang, self.sembako, self.perumahan, self.kesehatan, self.transportasi, self.informasi, self.rekreasi, self.pendidikan, self.penyedia_pangan, self.perawatan_pribadi ] # 过滤null值后求和,避免报错 return sum(f for f in fields if f is not None) def __str__(self): return str(self.tanggal) class Meta: verbose_name = "Inflasi" verbose_name_plural = "Inflasi"
修改admin.py
在Admin配置中显式添加计算属性到显示字段:
@admin.register(Inflasi) class InflasiModelAdmin(ImportExportModelAdmin): list_display = [ 'tanggal', 'sandang', 'sembako', 'perumahan', 'kesehatan', 'transportasi', 'informasi', 'rekreasi', 'pendidikan', 'penyedia_pangan', 'perawatan_pribadi', 'total_inflasi', 'calculated_total_inflasi' ] fields = list_display # 详情页显示相同字段
修改DRF序列化器
在序列化器中添加计算属性作为只读字段:
from rest_framework import serializers from .models import Inflasi class InflasiSerializer(serializers.ModelSerializer): calculated_total_inflasi = serializers.ReadOnlyField() class Meta: model = Inflasi fields = '__all__'
方案2:移除数据库字段,保留计算属性
如果不需要把total_inflasi存储到数据库,直接用计算属性:
修改models.py
删除total_inflasi数据库字段,保留@property并处理null值:
class Inflasi(models.Model): sandang = models.FloatField(null=True) sembako = models.FloatField(null=True) perumahan = models.FloatField(null=True) kesehatan = models.FloatField(null=True) transportasi = models.FloatField(null=True) informasi = models.FloatField(null=True) rekreasi = models.FloatField(null=True) pendidikan = models.FloatField(null=True) penyedia_pangan = models.FloatField(null=True) perawatan_pribadi = models.FloatField(null=True) tanggal = models.DateField(null=True) # 移除数据库字段total_inflasi @property def total_inflasi(self): fields = [ self.sandang, self.sembako, self.perumahan, self.kesehatan, self.transportasi, self.informasi, self.rekreasi, self.pendidikan, self.penyedia_pangan, self.perawatan_pribadi ] return sum(f for f in fields if f is not None) def __str__(self): return str(self.tanggal) class Meta: verbose_name = "Inflasi" verbose_name_plural = "Inflasi"
执行数据库迁移命令,移除数据库中的对应字段:
python manage.py makemigrations python manage.py migrate
修改admin.py
在Admin中添加计算属性,并设置为只读:
@admin.register(Inflasi) class InflasiModelAdmin(ImportExportModelAdmin): list_display = [ 'tanggal', 'sandang', 'sembako', 'perumahan', 'kesehatan', 'transportasi', 'informasi', 'rekreasi', 'pendidikan', 'penyedia_pangan', 'perawatan_pribadi', 'total_inflasi' ] fields = list_display readonly_fields = ['total_inflasi'] # 计算属性不可编辑
修改DRF序列化器
在序列化器中添加total_inflasi作为只读字段:
from rest_framework import serializers from .models import Inflasi class InflasiSerializer(serializers.ModelSerializer): total_inflasi = serializers.ReadOnlyField() class Meta: model = Inflasi fields = '__all__'
内容的提问来源于stack exchange,提问作者Amarulloh M Khoeri
相关产品推荐
相关产品推荐

