Django ModelForm外键字段更新时显示主键而非名称如何解决
问题解决方案
问题原因
你自定义的LocationField仅实现了clean()方法,该方法仅负责将表单提交的字符串值转换为Python层的City实例,但没有实现从模型已有的City实例转换为表单输入框初始展示值的逻辑,Django默认会取外键字段的主键值填充,因此出现了展示ID而非name的问题。
额外注意:你提供的
models.py中class Profile(models.Profile)属于笔误,实际开发中需要改为class Profile(models.Model),否则会报错。
解决方法
给自定义的LocationField添加prepare_value()方法,该方法负责将Python层的City实例转换为表单输入框需要展示的name值,修改后的forms.py代码如下:
from django import forms from django.core.exceptions import ObjectDoesNotExist from .models import Profile, City class LocationField(forms.CharField): def clean(self, value): try: city = City.objects.get(name=value) except ObjectDoesNotExist: city = City.objects.create(name=value) return city # 新增该方法即可实现初始值展示name的需求 def prepare_value(self, value): if isinstance(value, City): return value.name return super().prepare_value(value) class ProfileForm(forms.ModelForm): location = LocationField() class Meta: model = Profile exclude = ['user']
补充说明
prepare_value()是Django表单字段用来把Python类型的值转换为表单渲染时使用的原始值的钩子方法,刚好匹配你需要的「从City实例取name填充输入框」的需求- 原来的表单保存逻辑不需要做任何修改,原有功能不受影响
内容的提问来源于stack exchange,提问作者user17259141
相关产品推荐
相关产品推荐

