3đź‘Ť
Yes, this is possible, and like you’re suggesting the best thing for this is to use Wizard Forms. You can customize your wizard form using as many models as you want. I’ll show you a sample way to create a form in 2 steps:
- First Step with a form to generate a Parent object
- Second Step to generate a Child object
I want to point that in this case maybe you could think about making a dynamic second step, just in case a Parent can have more than one Child. I strongly recommedn you to check both documentation pages:
- Django Wizard Form: This are useful to separate big forms or join different forms in one
- Django Formsets This are useful to have some kind of “dynamic” forms
First Step: Create as many forms as you need for the wizard form (forms.py)
- This forms you’re going to create can be normal forms or ModelForms
-
Change “NameForm01” for the name you want for the form
class NameForm01 (forms.ModelForm):
class Meta:
model = Parent
fields = ['name', 'city']class NameForm02 (forms.ModelForm):
class Meta:
model = Child
# We don't add the parent field because we relate the child
# with the parent in the view
fields = ['name' ]
Second Step: Create the Wizard view (views.py)
from django.contrib.formtools.wizard.views import SessionWizardView
class YourNameWizard(SessionWizardView):
instance = None
form_list = [NameForm01, NameForm02]
template_name = "your_wizard_base.html" # Template used to render the forms
def done(self, form_list, **kwargs):
# Parent Information is in form 0
parent_name = form_list[0].cleaned_data['name']
parent_city = form_list[0].cleaned_data['city']
# Now we create the Parent object to relate with child
new_parent = Parent(name=parent_name, city=parent_city)
new_parent.save()
# Child information is in form 1
child_name = form_list[1].cleaned_data['name']
# Now we create the Child object related with new_parent
new_child = Child(name=child_name, parent=new_parent)
return HttpResponseRedirect(reverse('your_return_url'))
Third Step: Create the url to manage wizard forms (urls.py)
from YOUR_PROJECT.forms import NameForm01, NameForm02
from YOUR_PROJECT.views.content import YourNameWizard
# ... other imports you have in your urls.py ...
urlpatterns = patterns('',
# ... other patterns ...
url(r'^your/url/?$', YourNameWizard.as_view([NameForm01, NameForm02]), name='your_url_name'),
# ... other patterns ...
)
Fourth Step: Create the template the wizard form will use
This template is the example template that django offers in the documentation (here)
Following this example you should call this template “your_wizard_base.html” and place it in the Templates folder
{% extends "base.html" %}
{% load i18n %}
{% block head %}
{{ wizard.form.media }}
{% endblock %}
{% block content %}
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
<form action="" method="post">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
</table>
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">{% trans "first step" %}</button>
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">{% trans "prev step" %}</button>
{% endif %}
<input type="submit" value="{% trans "submit" %}"/>
</form>
{% endblock %}
This example template may be enough for you to practice with the WizardForm and then adapt it to your desires.