get_or_create для двух связанных моделей и наборов форм - PullRequest
1 голос
/ 25 мая 2011

У меня есть две модели, связанные с помощью ForeignKey и встроенных наборов форм:

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:
        #oredering=['cont']
        verbose_name_plural="Conturi"

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

У меня есть наборы форм, основанные на двух моделях.После того, как я отправляю форму, если «часть формы Balanta» существует, форма не должна ничего делать, если она не существует, она должна сохранить ее в базе данных (мне удалось это сделать).

Теперь, что я хочу сделать в «части формы Conturi», это посмотреть, находится ли продолжение в базе данных, форма должна обновить его, указав значение в поле ввода, и если его нет в базе данных,Форма должна создать его и соответствующий cont_debit или cont_credit.Текущее состояние дает мне: аргумент get_or_create () после ** должен быть отображением, а не списком.

Я думаю, что это нечто большее, чем простой / новый способ решения проблемы.

Здесьэто вид:

* ПОСЛЕДНЕЕ ОБНОВЛЕНИЕ *

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.models import inlineformset_factory

def balanta_introducere(request):
    balanta=Balanta()
    ConturiInlineFormSet=inlineformset_factory(Balanta, Conturi, extra=3)
    if  request.method=='POST':
        balanta_form=BalantaForm(request.POST, instance=balanta)
        if balanta_form.is_valid():
            balanta, created=Balanta.objects.get_or_create(**balanta_form.cleaned_data)
            #return HttpResponseRedirect('/sitfin/balantaok')
        formset=ConturiInlineFormSet(request.POST, request.FILES, instance=balanta)
        if formset.is_valid():
            #formset.save()
            for form in formset:
                data={
                        'cont':form.cleaned_data.get('cont'),
                        'cont_debit':form.cleaned_data.get('cont_debit'),
                        'cont_credit':form.cleaned_data.get('cont_credit'),
                        'balanta':form.cleaned_data.get('balanta'),
                }
                try:
                    c=Conturi()#.objects.get(cont=data['cont'])
                except Conturi.DoesNotExist:
                    cont_complete,created=Conturi.objects.get_or_create(**data)
                else:
                    for form in formset:
                        new_data={
                                'cont':form.cleaned_data.get('cont'),
                                'cont_debit':form.cleaned_data.get('cont_debit'),
                                'cont_credit':form.cleaned_data.get('cont_credit'),
                                'balanta':form.cleaned_data.get('balanta'),
                        }
                        cont_complete,created=Conturi.objects.get_or_create(**new_data)
    else:
        balanta_form=BalantaForm()
        formset=ConturiInlineFormSet(instance=balanta)
    return render_to_response('sitfin/balanta_introducere.html',{'balanta_form':balanta_form,'formset':formset}, context_instance=RequestContext(request))

1 Ответ

1 голос
/ 26 мая 2011

formset.cleaned_data - список отдельных форм cleaned_data.Вам нужно перебрать formset и создать Conturi объект для каждого:

if formset.is_valid():
    for form in formset:
        cont, created=Conturi.objects.get_or_create(**form.cleaned_data)

ОБНОВЛЕНИЕ:

Чтобы защитить себя от ошибок, возникающих в дополнительной формеполя, которые не соответствуют атрибутам модели, лучше явно указать аргументы для get_or_create вместо использования **form.cleaned_data.

if formset.is_valid():
   for form in formset:
       data = {
           'cont': form.cleaned_data.get('cont'),
           'cont_debit': form.cleaned_data.get('cont_debit'),
           'cont_credit': form.cleaned_data.get('cont_credit'),
           'balanta': form.cleaned_data.get('balanta'),
       }
       cont, created = Conturi.objects.get_or_create(**data)

Это в основном та же процедура, но теперь вы точно знаете, какие аргументыпередается в get_or_create.

...