Django Formsets添加了额外的实例

时间:2018-08-08 12:50:43

标签: django django-forms django-templates django-views

我正在构建一个应用程序,用户可以在其中添加优质商品。每个货件(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来动态添加和删除表单集实例,但是即使未激活该插件,问题仍然存在。

初始表单值是正确的,但是即使不涉及数据,总表单值也总是大于初始表单。

你们能帮我吗?这让我发疯了!

0 个答案:

没有答案
相关问题