I have two models set up in models.py: Parent and Child
class Parent(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField()
city = models.CharField()
class Child(models.Model):
id = models.AutoField(primary_key=True)
parent = models.ForeignKey(Parent)
name = models.CharField()
Now, during form entry for these, I'd like to make a FormWizard where the first form takes in Parent and the second view takes in details of Child while keeping the details of the previous form. Is this possible? And if so, please guide me through some code samples.
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:
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:
First Step: Create as many forms as you need for the wizard form (forms.py)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With