我正在构建一个应用程序,用户可以在其中添加优质商品。每个货件(DDT_IN)都有几个物料(DDT_IN_Item),每个物料都与该物料有关。当我尝试创建一个表单集以添加和修改这些货件时,该表单集会呈现不应存在的空字段。
这些是模型:
class ddt_in(models.Model):
class Meta:
verbose_name = 'Bolla In'
verbose_name_plural = 'Bolle In'
data = models.DateField()
numero = models.CharField(max_length=50)
fornitore= models.ForeignKey(laboratori,on_delete=models.CASCADE)
quantita = models.IntegerField(null=True, blank=True, default=0)
importo = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
doc_filename = models.FileField(upload_to="uploads/ddt_in/", blank=True, null=True)
def __str__(self):
return self.id
class ddt_in_item(models.Model):
class Meta:
verbose_name = 'Bolla In Items'
verbose_name_plural = 'Bolle In Items'
ddt = models.ForeignKey(ddt_in,on_delete=models.CASCADE, null=True, blank=True)
prodotti_var = models.ForeignKey(prodotti, on_delete=models.CASCADE, null=True, blank=True)
quantita = models.IntegerField()
costo_acquisto = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
iva = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
scade = models.DateField(null=True, blank=True)
def __str__(self):
return self.id
这些是以下形式:
class Ddt_inForm(forms.ModelForm):
class Meta:
model = ddt_in
fields = ("data", "numero", "fornitore", "doc_filename")
def clean_importo(self):
data = self.cleaned_data.get("importo")
return string_to_float(data)
def __init__(self, *args, **kwargs):
super(Ddt_inForm, self).__init__(*args, **kwargs)
self.fields["fornitore"].queryset = laboratori.objects.filter(is_active=True)
self.fields["fornitore"].widget.attrs.update({"class" : "m-select2 m-select2-lucy"})
self.fields["fornitore"].widget.attrs.update({ "style" : "width: 100%"})
self.fields["doc_filename"].widget.attrs.update({"class" : "custom-file-input"})
class Ddt_in_itemForm(forms.ModelForm):
class Meta:
model = ddt_in_item
fields = ("prodotti_var", "quantita", "scade")
def __init__(self, *args, **kwargs):
super(Ddt_in_itemForm, self).__init__(*args, **kwargs)
self.fields["scade"].required = False
self.fields["prodotti_var"].queryset = prodotti.objects.order_by("nome_prodotto").filter(is_active=True)
#self.fields["prodotti_var"].widget.attrs.update({"class" : "form-control m-bootstrap-select m_selectpicker"})
class BaseDdtInFormSet(forms.BaseModelFormSet):
def clean(self):
prodotti_selezionati = []
duplicates = False
super().clean()
for form in self.forms:
if form.cleaned_data:
prodotto = form.cleaned_data["prodotti_var"]
if not prodotto:
raise forms.ValidationError("Seleziona un prodotto")
quantita = form.cleaned_data["quantita"]
if not quantita:
raise forms.ValidationError("Seleziona il numero di prodotti")
if prodotto:
if prodotto in prodotti_selezionati:
duplicates = True
prodotti_selezionati.append(prodotto)
if duplicates:
raise forms.ValidationError("Non selezionare due volte lo stesso prodotto")
class BaseItemInlineFormset(forms.BaseInlineFormSet):
def clean(self):
prodotti_selezionati = []
duplicates = False
super(BaseItemInlineFormset, self).clean()
for form in self.forms:
if form.cleaned_data:
prodotto = form.cleaned_data["prodotti_var"]
if not prodotto:
raise forms.ValidationError("Seleziona un prodotto")
quantita = form.cleaned_data["quantita"]
if not quantita:
raise forms.ValidationError("Seleziona il numero di prodotti")
if prodotto in prodotti_selezionati:
duplicates = True
prodotti_selezionati.append(prodotto)
if duplicates:
raise forms.ValidationError("Non selezionare due volte lo stesso prodotto")
ItemFormset = forms.inlineformset_factory(ddt_in, ddt_in_item, formset=BaseItemInlineFormset, fields=("prodotti_var", "quantita", "scade"), min_num=1, validate_min=True)
这些是视图:
def ddt_in_add(request):
if not request.user.is_authenticated or not can_view(request):
return redirect("/")
#prodotti_nb = prodotti.objects.filter(is_active=True)
ProdottiFormSet = modelformset_factory(ddt_in_item, form=Ddt_in_itemForm, formset=BaseDdtInFormSet)
if request.method == "POST":
totale = decimal.Decimal(0.00)
ddt_in_form = Ddt_inForm(request.POST, request.FILES)
ddt_item_forms = ProdottiFormSet(request.POST)
if ddt_in_form.is_valid() and ddt_item_forms.is_valid():
bolla = ddt_in_form.save()
products = ddt_item_forms.save(commit=False)
for instance in products:
instance.ddt = bolla
instance.costo_acquisto = instance.quantita * instance.prodotti_var.costo_acquisto
totale += instance.costo_acquisto
instance.iva = instance.prodotti_var.iva
bolla.quantita += instance.quantita
instance.save()
bolla.importo = totale
bolla.save()
messages.success(request, "Bolla aggiunta con successo")
return redirect("/magazzino/bolle_in/")
else:
ddt_in_form = Ddt_inForm()
ddt_item_forms = ProdottiFormSet()
context = {"ddt_form" : ddt_in_form, "ddt_item_formset" : ddt_item_forms, "title": "Aggiungi laboratorio", "parent":"Magazzino","page_title": "Bolla IN", "form_title": "Aggiungi Bolla", "pul": "Salva", "link_back":"/magazzino/bolle_in/"}
return render(request, "ddt_in_add.html", context)
def ddt_in_detail(request, id=None):
if not request.user.is_authenticated or not can_view(request):
return redirect("/")
ddt_instance = get_object_or_404(ddt_in, id=id)
totale = decimal.Decimal(0.00)
if request.method == 'POST':
formset = ItemFormset(request.POST, instance=ddt_instance)
ddt_form = Ddt_inForm(request.POST, instance=ddt_instance)
if ddt_form.is_valid() and formset.is_valid():
ddt_instance = ddt_form.save()
ddt_instance.quantita = 0
products = formset.save(commit=False)
for instance in products:
instance.ddt = ddt_instance
instance.costo_acquisto = instance.quantita * instance.prodotti_var.costo_acquisto
totale += instance.costo_acquisto
instance.iva = instance.prodotti_var.iva
ddt_instance.quantita += instance.quantita
instance.save()
ddt_instance.importo = totale
ddt_instance.save()
messages.success(request, "Bolla In modificata con successo")
return redirect("/magazzino/bolle_in/")
else:
ddt_form = Ddt_inForm(instance=ddt_instance)
formset = ItemFormset(instance=ddt_instance)
context = {"formset" : formset, "ddt_form": ddt_form, "ddt" : ddt_instance, "title" : ddt_instance.numero, "parent":"Magazzino", "page_title": "Bolla IN", "form_title": "Modifica Bolla IN " + ddt_instance.numero ,"pul": "Modifica", "link_back":"/magazzino/bolle_in/"}
return render(request, "ddt_in_mod.html", context)
这是模板:
{{ formset.management_form }}
{% for form in formset %}
<div class="form-group m-form__group row formset">
{{form.id}}
<label for="id_form-{{forloop.counter0}}-prodotti_var" class="col-lg-2 col-form-label">Prodotto</label>
<div class="col-lg-3 validate-field">
{% bootstrap_field form.prodotti_var show_label=False form_group_class="" field_class=""%}
</div>
<label for="id_form-{{forloop.counter0}}-quantita" class="col-lg-1 col-form-label">Quantità</label>
<div class="col-lg-1 validate-field">
{% bootstrap_field form.quantita show_label=False form_group_class="" %}
</div>
<label for="id_form-{{forloop.counter0}}-scade" class="col-lg-1 col-form-label">Scadenza</label>
<div class="col-lg-1 validate-field">
{% bootstrap_field form.scade show_label=False form_group_class="" %}
</div>
</div>
{% endfor %}
我还使用django-formset plugin for jquery来动态添加和删除表单集实例,但是即使未激活该插件,问题仍然存在。
初始表单值是正确的,但是即使不涉及数据,总表单值也总是大于初始表单。
你们能帮我吗?这让我发疯了!