表单中的 Django .initial 属性似乎不起作用

问题描述 投票:0回答:1

我的 Django 项目有问题。我有一个模型“Fattura”和一个表单“EntrataForm”,这是模型的代码:

class Fattura(models.Model):
    TIPO_CHOICES = [
        ('T', 'Tasse'),
        ('B', 'Burocrazia'),
        ('C', 'Clienti'),
        ('S', 'Spese'),
    ]

    numero = models.CharField(max_length=20)
    data = models.DateField(default=django.utils.timezone.now)
    tipo = models.CharField(max_length=1, choices=TIPO_CHOICES)
    importo = models.DecimalField(max_digits=10, decimal_places=2)
    cliente = models.ForeignKey(Cliente, on_delete=models.CASCADE, null=True, blank=True)
    viaggi = models.ManyToManyField(Viaggio)

    def clean(self):
        if self.importo is None:
            raise ValidationError('L\'importo non può essere None.')

    def __str__(self):
        return f"{self.numero} - {self.data} - {self.importo} - {self.tipo}"

和形式:


class EntrataForm(forms.ModelForm):
    class Meta:
        model = Fattura
        fields = ['numero', 'data', 'cliente','viaggi','importo','tipo']


    def __init__(self, *args, **kwargs):
        id = kwargs.pop('id',None)
        super(EntrataForm, self).__init__(*args, **kwargs)
        importo_finale = 0
        viaggi = Viaggio.objects.filter(cliente_id=id)
        for viaggio in viaggi:
            importo_finale += viaggio.prezzo_viaggio
        print(id)

        self.fields['tipo'].widget.attrs['readonly'] = True
        self.fields['tipo'].required = False
        self.fields['tipo'].widget = forms.HiddenInput()
        self.fields['tipo'].initial = 'C'
        self.fields['viaggi'].widget.attrs['readonly'] = True
        self.fields['viaggi'].required = False
        self.fields['viaggi'].widget = forms.HiddenInput()
        self.fields['viaggi'].initial = viaggi
        self.fields['cliente'].widget.attrs['readonly'] = True
        self.fields['cliente'].required = False
        self.fields['cliente'].widget = forms.HiddenInput()
        self.fields['cliente'].initial = Cliente.objects.get(id=id)
        self.fields['importo'].widget.attrs['readonly'] = True
        self.fields['importo'].required = False
        self.fields['importo'].widget = forms.HiddenInput()
        self.fields['importo'].initial = importo_finale
        print(self.fields['importo'].initial)

如您所见,我对 4 个字段使用了“.initial”属性,但只有“importo”未正确初始化。在 init 中,最终值是正确的,最后一行打印我想要的内容,但是当它返回到视图并执行 form.is_valid() 行时,它会引发 ValidationError,因为“importo”是 None 。其他字段没有这个错误,但是程序是一样的,我不明白值“importo”在哪里变成了None。

查看代码如下:

def entrata(request, id):
    viaggi = Viaggio.objects.filter(cliente_id=id)
    cliente = Cliente.objects.get(id=id)
    if request.method == 'POST':
        form = EntrataForm(request.POST, id=id)
        if form.is_valid():
            nuova_fattura = form.save()

            return redirect('fatture')
        else:
            # Se il form non è valido, potresti restituire un template renderizzato
            print(form.errors)
            return redirect('fatture')

    else:

        form = EntrataForm(id=id)


        return render(request, 'fatture/crea/cliente/entrata.html', {'form': form, 'cliente': cliente, 'viaggi':viaggi})

这是模板:

{% extends 'fatture/index.html' %}

{% block corpo %}
<body>
    <button onclick="location.href = '{% url 'fatture' %}'" id="indietro">Indietro</button>
    <section>
        <h2>Viaggi per {{ cliente }}</h2>
        <h3>Seleziona i viaggi che vuoi inserire nella fattura</h3>
        <div id="banner">
            <form id="fattura-form" method="post" action="{% url 'entrata' cliente.id%}">
    {% csrf_token %}

    <label for="{{ form.numero.id_for_label }}">Numero:</label>
    {{ form.numero }}
    <br>

    <label for="{{ form.data.id_for_label }}">Data:</label>
    {{ form.data }}
    <br>



    <button type="submit">Inserisci</button>
</form>

            <table id="tabella-fatture" style="margin-top: 30px;">
    <thead>
        <tr>
            <th>Data</th>
            <th>Distanza</th>
            <th>Prezzo Viaggio</th>
        </tr>
    </thead>
    <tbody>
        {% for viaggio in viaggi %}
            <tr>
                <td>{{ viaggio.data_viaggio }}</td>
                <td>{{ viaggio.distanza_km }}</td>
                <td>{{ viaggio.prezzo_viaggio }}</td>
            </tr>
        {% endfor %}
    </tbody>
</table>
    </div>
    </section>

</body>

{% endblock %}

更新

我更改了模板,我用 {{form.as_p}} 而不是两个表单值,现在问题也出在其他字段上。现在的form.error是:

<ul class="errorlist"><li>viaggi<ul class="errorlist"><li>&quot;&quot; non � un valore valido.</li></ul></li><li>importo<ul class="errorlist"><li>Questo campo � obbligatorio.</li></ul></li><li>tipo<ul class="errorlist"><li>Questo campo � obbligatorio.</li></ul></li><li>__all__<ul class="errorlist nonfield"><li>L&#x27;importo non pu� essere None.</li></ul></li></ul>
python django django-forms
1个回答
0
投票

您没有在模板中呈现该字段,因此在发布表单时不包含该字段及其初始值。视图中请求的 POST 数据不包含

importo
字段,并且表单是使用该不完整的数据实例化的。并且您在 init 方法中设置的初始值无法替代数据中缺少的值:

使用initial在运行时声明表单字段的初始值。 ...这些值仅针对未绑定的表单显示,如果未提供特定值,它们不会用作后备值。

https://docs.djangoproject.com/en/4.2/ref/forms/api/#initial-form-values

由于模型需要

importo
(
null!=True
) 的值,因此表单验证“通常”会在此处失败,并显示需要 importo 的消息。但是您在表单 init 方法中将
importo
设置为不需要,这意味着表单验证至少首先通过。然后,模型上的自定义 clean 方法会触发验证错误,因为从未设置
importo
的值,即它仍然是
None
    

© www.soinside.com 2019 - 2024. All rights reserved.