Django Subgroup模型两个关联Group的ForeignKey字段模板渲染值相同
问题产生原因
Subgroup模型中的group_number和group_in_name都是指向Group模型的外键字段,Django表单默认对外键字段生成ModelChoiceField下拉选项时,会调用关联模型(即Group)的__str__方法生成选项文本,你的Group模型的__str__固定返回group_name,所以两个下拉框的选项文本完全一致。- 从模型设计逻辑来看,两个外键本质关联的是同一个Group实例的话,两个字段存储的都是同一个Group的主键值,最终渲染出来的结果自然完全相同,这种双外键指向同一张表的设计本身存在冗余问题,不符合数据库范式。
修复方案
你可以根据自己的业务需求选择以下任意一种方案:
场景1:确实需要保留两个外键字段,让两个下拉框分别展示Group的编号和名称
你需要在AddSubgroupForm表单类中,自定义两个外键字段的选项展示逻辑,重写label_from_instance方法:
from django import forms from .models import Subgroup, Group class GroupNumberChoiceField(forms.ModelChoiceField): def label_from_instance(self, obj): return obj.group_num class GroupNameChoiceField(forms.ModelChoiceField): def label_from_instance(self, obj): return obj.group_name class AddSubgroupForm(forms.ModelForm): group_number = GroupNumberChoiceField(queryset=Group.objects.all()) group_in_name = GroupNameChoiceField(queryset=Group.objects.all()) class Meta: model = Subgroup fields = ['sub_group_num', 'sub_group_name', 'group_number', 'group_in_name']
修改后group_number下拉框会展示所有Group的编号,group_in_name下拉框会展示所有Group的名称。
场景2:更合理的方案,优化冗余的模型设计
实际上Subgroup只需要关联一个Group即可,不需要设置两个外键,关联后可以直接通过外键取到对应Group的编号和名称,修改如下:
- 首先修改
Subgroup模型,删除冗余外键:
class Subgroup(models.Model): sub_group_num = models.CharField(max_length=100) sub_group_name = models.CharField(max_length=200) group = models.ForeignKey(Group, on_delete=models.CASCADE, related_name='subgroups', verbose_name="所属分组") def __str__(self): return self.sub_group_name
- 如果需要在页面同时展示所属Group的编号和名称,直接通过外键关联取值即可,详情页可以直接用如下写法,表单页需要联动的话加少量JS即可实现:
<div class="col-md-2"> <label>所属分组</label> </div> <div class="col-md-10 form-group"> {{ form.group }} </div> <p>分组编号:{{ subgroup.group.group_num }}</p> <p>分组名称:{{ subgroup.group.group_name }}</p>
这种方案避免了数据冗余,也不会出现两个字段值相同的问题。
内容的提问来源于stack exchange,提问作者Umar Milanzi Snr
相关产品推荐
相关产品推荐

