2

在我的应用程序中,用户可以创建和编辑报告。呈现报表编辑页面时,字段会填充初始数据。
我遇到了以下问题——其中一个字段(运算符)没有显示我通过初始参数在视图中传递给它的值。相反,该字段要么保持为空,要么采用默认值,具体取决于设置。所有其他字段都填充了初始数据,没有错误。
我正在使用 Formsets,问题字段是 ModelChoiceField。初始数据取自 json 数组。
据我所知,HTML 代码 - 在问题字段“operator”中,在“option”标签(它似乎是由 Select 小部件生成)中缺少“selected”属性。但是如何把这个属性放在那里还不清楚。更令人困惑的是,“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",null=True, 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'  
   },  
]

该列表可以包含一个或多个字典。基于表单集中的字段数。

4

1 回答 1

0

@NKSM 在评论中告诉我,我应该Operator在“运算符”字段中传递对象的主键。我在那里传递了对象的名称。
我重写了OperatorEncoder

class OperatorEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Operator):
            return obj.idOperator
        return json.JSONEncoder.default(self, obj)

现在一切正常。

于 2021-04-26T20:27:25.727 回答