Django: How to save a formset based on two models

2019-04-08 18:18发布

I am having difficult times saving a formset to the database. I have 2 models, one having a ForeignKey to the other(I made some entries for Balanta model in Django admin page):

models.py

    class Balanta(models.Model):
    data=models.DateField()

    class Meta:
        ordering=['data']
        verbose_name_plural="Balante"

    def __unicode__(self):
        return unicode(self.data)


class Conturi(models.Model):
    cont=models.PositiveIntegerField()
    cont_debit=models.DecimalField(default=0, max_digits=30, decimal_places=2)
    cont_credit=models.DecimalField(default=0, max_digits=30, decimal_places=2)
    balanta=models.ForeignKey(Balanta)

    class Meta:
        #ordering=['cont']
        verbose_name_plural="Conturi"

    def __unicode__(self):
        return unicode(self.cont)

next i made a forms.py:

from sitfin.models import Conturi, Balanta
from django.forms import ModelForm

class BalantaForm(ModelForm):
    class Meta:
        model=Balanta

class ConturiForm(ModelForm):
    class Meta:
        model=Conturi

and the views.py:

from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
from sitfin.models import Balanta, Conturi
from sitfin.forms import BalantaForm, ConturiForm
from django.forms.formsets import formset_factory

def conturi_index(request):
    return render_to_response('sitfin/conturi_index.html',{'conturi_list':Conturi.objects.all()})

def conturi_introducere(request):
    ConturiFormSet=formset_factory(ConturiForm)
    if request.method=='POST':
        #form=ConturiForm(data=request.POST)
        conturi_formset=ConturiFormSet(request.POST, request.FILES)
        #if form.is_valid():
        if conturi_formset.is_valid():
            for form in conturi_formset.cleaned_data:
                balanta=Balanta(data=form['data'])
                balanta.save()
                cont=Conturi(cont=form['cont'])
                cont.save()
                return HttpResponseRedirect("sitfin/conturiok")
    else:
        #form=ConturiForm()
        conturi_formset=ConturiFormSet()
    #return render_to_response('sitfin/conturi_introducere.html',{'form':form})
    return render_to_response('sitfin/conturi_introducere.html',{'conturi_formset':conturi_formset}, context_instance=RequestContext(request))

and the template:

<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">

    <title>Conturi_introducere</title>

</head>
<body>
    <p>BAGA CONTURILE</p>
    <form action="" method="post">{% csrf_token %}
        {{ conturi_formset.management_form }}
        <table border="0">
            {% for cform in conturi_form %}
            {{ cform }}
            {% endfor %}
        </table>

    <p><input type="submit" value="Submit"></p>
    </form>
</body>
</html>

I manage to have a form which is a formset with the fields in Conturi model(with foreign key to Balanta model) and below the field in Balanta model but when i press submit i get KeyError 'data'. This is the error at this step but i get errors which i managed to overcome like balanta_id cannot be null, or something about tampering with the management_form.

I want to save the Conturi formset based on the date i'm choosing from the drop-down(the date is prepopulated but i could also enter it by hand) and later in the development i will try to add a jquery to add more Conturi fields in the form and after that to save all the formset in the database, but it's waaaaaaay too far from my problem.

Thank You very much!

1条回答
孤傲高冷的网名
2楼-- · 2019-04-08 19:01

Check this out: http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#inline-formsets This really simplifies the related by foreign-keys use case which should perfectly fit you.

You shouldn't iterate over the cleaned_data like you do, a simple form.save() should do it. Also, it strikes me as odd that you would iterate over the form rather than the formset in the template. I'm super sleepy atm, so I dunno. And your code does not return a response when the formset isn't valid. You'll get a 500 error for that.

Basically you should use a form for the Balanta model and a inline formset for the other one. Then you can carry out the validation in two parts: if formset is valid... and if form is valid...

查看更多
登录 后发表回答