Using two models in one FormWizard

I have two models configured in models.py

: Parent

andChild

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, while entering the form for this, I would like to do FormWizard

where the first form takes Parent

on and the second takes on details Child

, keeping the details of the previous form. Is it possible? And if so, please check me through some code samples.

+3


source to share


1 answer


Yes it is possible, and as you suggest, it is best to use Wizard Forms . You can customize your wizard shape using as many models as you like. I'll show you an example of how to create a form in 2 steps:

  • The first step with a form to create a Parent object
  • Second step for creating child object

I want to point out that in this case, perhaps you could consider doing a dynamic second step, in case the parent can have more than one child. I strongly recommended that you check both documentation pages:

  • Django Wizard Form : This is useful for splitting large forms or combining different forms into one
  • Django Formsets It's useful to have some kind of "dynamic" forms

First step: create as many forms as needed for the master form (forms.py)

  • These forms you are about to create can be Normal Forms or ModelForms
  • Change "NameForm01" to 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 a master 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 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 a template in which the wizard form will be created

This template is an example of a 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 sample template may be enough for you to practice with the WizardForm and then adapt it to your wishes.

+3


source







All Articles