I have a form wizard in Django. In the first step I need to insert data about a transport request, and a message, which is in another model. In second step I add passengers using a formset, and in the last one, the addresses, also in a formset.
I don't know how to insert the message field in the first step. I tried to add a formset in the context overriding the get_context_data method from the SessionWizardView (code below). It shows the field, but I couldn't figure it out how to save it.
I saw this post Django form with fields from two different models, but the SessionWizardView does not allow me to add a view with two forms in a step, I can only add forms.
I have also read this one django wizard, using form and formset in the same step, but it doesn't works, maybe because it is from 6 years ago.
My last try was to add a custom field in the transport ModelForm (not in the code below), but I think it will not be the right way to do it (I still don't know how to save the message this way).
The code is like this:
models.py
class Transporte(models.Model):
#fields about transport here
class Mensagem(models.Model):
#this is the message field
mensagem = models.TextField("Mensagem", blank=True)
transporte = models.ForeignKey(Transporte, on_delete=models.CASCADE)
...
forms.py
class FormTransporte(forms.ModelForm):
class Meta:
model = Transporte
class FormMensagem(forms.ModelForm):
class Meta:
model = Mensagem
exclude = ()
FormsetMensagem = inlineformset_factory(Transporte, Mensagem, form=FormMensagem,extra=1)
...
views.py
FORMS = [("base", FormTransporte),
("passageiros",FormsetPassageiros),
("enderecos",FormsetEnderecos)
]
TEMPLATES = {"base":'transporte/solicitar.html',
"passageiros":'transporte/passageiros.html',
"enderecos":'transporte/enderecos.html'}
class WizardView(SessionWizardView):
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
def get_context_data(self,form, **kwargs):
#Here I try to append the formset in the first step. It shows the
#field, but no success on saving it
data = super(WizardView,self).get_context_data(form,**kwargs)
if self.steps.current == "base":
if self.request.POST:
data['mensagem'] = FormsetMensagem(self.request.POST)
else:
data['mensagem'] = FormsetMensagem()
return data;
def done(self,form_list,form_dict,**kwargs):
form_transporte = form_dict['base']
#the line below doesn't works
form_mensagem = form_dict['base']['mensagem']
instance_transporte = form_transporte.save()
if 'enderecos' in form_dict:
formset_endereco = form_dict['enderecos']
for form_endereco in formset_endereco:
endereco = form_endereco.save(commit=False)
endereco.transporte = instance_transporte
endereco.save()
if 'passageiros' in form_dict:
formset_passageiros = form_dict['passageiros']
for form_passageiros in formset_passageiros:
passageiros = form_passageiros.save(commit=False)
passageiros.transporte = instance_transporte
passageiros.save()
return render(self.request,'transporte/done.html',{
'form_data': [form.cleaned_data for form in form_list],
})
...
urls.py
app_name = 'transporte'
urlpatterns = [
...
path(r'solicitar/',login_required(views.WizardView.as_view(views.FORMS, condition_dict={'passageiros': views.tem_passageiros})), name='solicitar'),
...
]
Any ideas?