Reputation: 465
I have two ModelForm objects in the same view - Person and Adress. After user has bounded , I'm saving Person object. After saving, I want to use that saved object to set the ForeignKey of AdressForm, validate that form, and save. How can I set this? I mean field in ModelForm()? I've searched everywhere, and ewerywhere is said I have to save(commit=False), but I can't save unvalidated form! When I valid(), there is blank ForeignKey field! Here's my code: (I try to avoid create method, rather save)
views.py
class KontrahentCreate(LoginRequiredMixin, generic.View):
template = 'escrm/kontrahent_form.html'
context = dict()
message = "Utworzono pomyślnie nowego kontrahenta"
def get(self, request):
self.context['form_kontrahent'] = KontrahentForm(initial={'czy_aktywny': True})
self.context['form_kontrahent'].fields['czy_aktywny'].widget = HiddenInput()
self.context['form_adres'] = AdresKontrahentForm(initial={'czy_domyslny': True})
self.context['form_adres'].fields['czy_domyslny'].widget = HiddenInput()
self.context['title'] = 'Dodaj nowego kontrahenta'
return render(request, self.template, self.context)
def post(self, request):
kontrahent_form = KontrahentForm(request.POST)
adres_form = AdresKontrahentForm(request.POST)
if kontrahent_form.is_valid():
kontrahent = kontrahent_form.save()
else:
self.context['form_kontrahent'] = kontrahent_form
return render(request, self.template, self.context)
adres_form['kontrahent'].data = kontrahent.pk #AttributeError can't set attribute
if adres_form.is_valid():
adres_form.save()
else:
self.context['form_adres'] = adres_form
return render(request, self.template, self.context)
messages.success(self.request, self.message)
return HttpResponseRedirect(reverse_lazy('escrm:kontarhent-detail', kwargs={'pk': kontrahent.pk}))
forms.py
class KontrahentForm(ModelForm):
class Meta(ModelForm):
model = Kontrahent
fields = '__all__'
class AdresKontrahentForm(ModelForm):
class Meta(ModelForm):
model = AdresKontrahent
fields = '__all__'
widgets = {
'kontrahent': forms.HiddenInput(),
}
Upvotes: 0
Views: 405
Reputation: 73450
You should exclude the kontrahent
field from the adres form. Then the form will be valid without it! I added some other modifications (e.g. do not make your context a class variable). Also for the other fields that you provide initial values and hidden inputs for, consider excluding them from the form altogether. If you give them default values in the model, you can ignore them in the view, too:
class KontrahentForm(ModelForm):
class Meta(ModelForm):
model = Kontrahent
exclude = ['czy_aktywny'] # consider default value on model!
class AdresKontrahentForm(ModelForm):
class Meta(ModelForm):
model = AdresKontrahent
exclude = ['czy_domyslny', 'kontrahent']
# view
def get_form(self, formclass):
if request.method == 'POST':
return formclass(request.POST)
return formclass()
def get_context(self, **kwargs):
ctx = {}
ctx['form_kontrahent'] = kwargs.get('kontrahent_form', self.get_form(KontrahentForm))
ctx['form_adres'] = kwargs.get('adres_form', self.get_form(AdresKontrahentForm))
ctx['title'] = 'Dodaj nowego kontrahenta'
return ctx
def get(self, request):
return render(request, self.template, self.get_context())
def post(self, request):
kontrahent_form = self.get_form(KontrahentForm)
adres_form = self.get_form(AdresKontrahentForm)
k_valid = kontrahent_form.is_valid()
a_valid = adres_form.is_valid()
if not (k_valid and a_valid):
return render(
request, self.template,
self.get_context(kontrahent_form=kontrahent_form, adres_form=adres_form))
kontrahent = kontrahent_form.save(commit=False)
kontrahent.czy_aktywny = True
kontrahent.save()
adres = adres_form.save(commit=False)
adres.czy_domyslny = True
adres.kontrahent = kontrahent
adres.save()
messages.success(self.request, self.message)
return HttpResponseRedirect(reverse_lazy('escrm:kontarhent-detail', kwargs={'pk': kontrahent.pk}))
Upvotes: 1
Reputation: 599490
In all those places that said to use save(commit=False)
, they will also say that you should exclude the field from the form, rather than using fields = '__all__'
. That way, the form won't be invalid.
Upvotes: 1