如何解决表单集 ModelChoiceField 中无法显示初始数据
在我的应用程序中,用户可以创建和编辑报告。渲染报表编辑页面时,字段会填充初始数据。
我遇到了以下问题 - 其中一个字段(运算符)没有显示我通过初始参数在视图中传递给它的值。相反,该字段要么保持为空,要么采用默认值,具体取决于设置。所有其他字段都填充了初始数据,没有错误。
我正在使用 Formsets,问题字段是 ModelChoiceField。初始数据取自json数组。
据我了解的 HTML 代码 - 在问题字段“操作员”中,在“选项”标签(它似乎是由选择小部件生成的)中缺少“选择”属性。但是如何把这个属性放在那里并不清楚。更令人困惑的是,“eq_type”字段(也是一个选择字段)的显示没有错误。 “已选择”出现在所需选项旁边。
也许有人遇到过类似的?请告诉我可能是什么问题。
forms.py 的片段:
class AMSEquipmentForm(forms.Form):
EQ_TYPES = (
('panel_antenna','панельная антенна'),('RRL_antenna','РРЛ антенна'),('radio_module','радиомодуль')
)
eq_type = forms.ChoiceField(choices=EQ_TYPES,label='Тип')
height = forms.IntegerField(label='Высота')
proportions = forms.IntegerField(label='Размеры')
amount = forms.IntegerField(label='Количество')
manufacturer = forms.CharField(max_length=50,label='Производитель')
model = forms.CharField(max_length=50,label='Модель')
operator = forms.ModelChoiceField(queryset=Operator.objects.all(),label='Оператор') # Проблемное поле
note = forms.CharField(max_length=100,label='Примечание')
eq_type.widget.attrs.update({'class': 'formset-field'})
height.widget.attrs.update({'class': 'formset-field'})
proportions.widget.attrs.update({'class': 'formset-field'})
amount.widget.attrs.update({'class': 'formset-field'})
manufacturer.widget.attrs.update({'class': 'formset-field'})
model.widget.attrs.update({'class': 'formset-field'})
operator.widget.attrs.update({'class': 'formset-field'}) # Проблемное поле
note.widget.attrs.update({'class': 'formset-field'})
views.py 的片段:
def report_update(request,pk):
EquipmentFormset = formset_factory(AMSEquipmentForm,max_num=1)
report = Report.objects.get(idReport=pk)
form = ReportModelForm(instance=report)
formset = EquipmentFormset(initial=json.loads(report.reportEquipAms),prefix='reports_report') # Здесь передаю начальные данные
if request.method == 'POST':
form = ReportModelForm(request.POST or None)
formset = EquipmentFormset(request.POST or None,prefix='reports_report')
if form.is_valid() and formset.is_valid():
report.reportYear = form.cleaned_data['reportYear']
report.reportObject_id = form.cleaned_data['reportObject']
report.reportTemplate_id = form.cleaned_data['reportTemplate']
report.reportTeam_id = form.cleaned_data['reportTeam']
report.reportEquipment_id = form.cleaned_data['reportEquipment']
report.reportWind = form.cleaned_data['reportWind']
report.reportWeather = form.cleaned_data['reportWeather']
report.reportSoil = form.cleaned_data['reportSoil']
report.reportTemp = form.cleaned_data['reportTemp']
report.reportWeather3 = form.cleaned_data['reportWeather3']
report.reportElVoltage = form.cleaned_data['reportElVoltage']
report.reportElCableL = form.cleaned_data['reportElCableL']
report.reportElCableR = form.cleaned_data['reportElCableR']
report.reportElRope = form.cleaned_data['reportElRope']
report.reportElBus = form.cleaned_data['reportElBus']
report.reportMeasuresDate = form.cleaned_data['reportMeasuresDate']
report.reportData = form.cleaned_data['reportData']
report.reportEquipAms = json.dumps(formset.cleaned_data,cls=OperatorEncoder,ensure_ascii=False)
report.save()
return redirect('reports:report-list')
context = {
'report': report,'form': form,'formset': formset
}
return render(request,"reports/report_update.html",context)
models.py 的片段:
class Operator(models.Model):
idOperator = models.AutoField(primary_key=True)
operatorName = models.CharField(max_length=45)
operatorReport = models.ForeignKey("Report",null=True,on_delete=models.SET_NULL)
operatorContract = models.ForeignKey("Contract",on_delete=models.SET_NULL)
def __str__(self):
return self.operatorName
class Meta:
verbose_name = "Оператор"
verbose_name_plural = "Операторы"
在浏览器中显示通过代码检查器查看的字段:
字段eq_type:
<select name="reports_report-1-eq_type" class="formset-field" id="id_reports_report-1-eq_type">
<option value="panel_antenna">панельная антенна</option>
<option value="RRL_antenna" selected>РРЛ антенна</option>
<option value="radio_module">радиомодуль</option>
</select>
字段运算符:
<select name="reports_report-1-operator" class="formset-field" id="id_reports_report-1-operator">
<option value="8">Оператор3</option>
<option value="9">Оператор2</option>
<option value="10">Оператор1</option>
</select>
负责表单的html模板片段:
{% for equipment in formset %}
<tr class="item">
<td>
{{ equipment.eq_type }}
</td>
<td>
{{ equipment.height }}
</td>
<td>
{{ equipment.proportions }}
</td>
<td>
{{ equipment.amount }}
</td>
<td>
{{ equipment.manufacturer }}
</td>
<td>
{{ equipment.model }}
</td>
<td>
{{ equipment.operator }}
</td>
<td>
{{ equipment.note }}
</td>
<td>
<button type="button" class="btn btn-danger btn-sm remove-form-row" id="{{ formset.prefix }}">Delete</button>
</td>
</tr>
{% endfor %}
更新
我在 reportEquipAms
中传输的初始数据如下所示:
[
{
'eq_type': 'panel_antenna','height': 18,'proportions': 10,'amount': 1,'manufacturer': 'manufacturer_name','model': 'some model','operator': 'Оператор2',# Operator class object
'note': 'some note'
},]
该列表可以包含一个或多个词典。基于表单集中的字段数。
解决方法
@NKSM 在评论中告诉我,我应该在“operator”字段中传递 Operator
对象的主键。我在那里传递了对象的名称。
我重写了OperatorEncoder
:
class OperatorEncoder(json.JSONEncoder):
def default(self,obj):
if isinstance(obj,Operator):
return obj.idOperator
return json.JSONEncoder.default(self,obj)
现在一切正常。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。