Search code examples
pythondjangodjango-formsdjango-formwizard

django form wizard - NoReverseMatch - looking for a specific named step


I'm trying to setup a multi-step form using Django Form Wizard, but running into a "NoReverseMatch" error.

From previous experience with this error, it was because I was not passing through an argument when the url takes one, i.e. (?P<pk>\d+).

In my specific case: Reverse for 'task_step' with arguments '()' and keyword arguments '{'step': u'address'}' not found. 0 pattern(s) tried: []

What I've tried so far:

  • passing wizard.steps.current in the <form action="">
  • passing wizard.steps.next in the <form action="">

Is it something to do with my urls.py?

// views.py

FORMS = [("subcategory", ChooseSubcategoryForm),
                    ("address", SetAddressForm),
                    ("task-details", AddTaskDetailsForm),]

TEMPLATES = {"subcategory": "tasks/create_task_form/step1.html",
                        "address": "tasks/create_task_form/step2.html",
                        "task-details": "tasks/create_task_form/step3.html",
}
class AddTaskWizard(NamedUrlSessionWizardView):

    form_list = [ChooseSubcategoryForm, SetAddressForm, AddTaskDetailsForm]

    def get_template_names(self):
        return [TEMPLATES[self.steps.current]]

    def get_context_data(self, form, **kwargs):
        context = super(AddTaskWizard, self).get_context_data(form=form, **kwargs)
        # add extra variables for a specific step
        # if self.steps.current == "step_name":
        #   context.update({'another_variable': True})
        return context

    def done(self, form_list, form_dict, **kwargs):
        # do something with the form data(form_list)
        subcategory = form_dict['subcategory'].save()
        print("============")
        print(subcategory)
        print("============")
        address = form_dict['address'].save()
        task = form_dict['task-details'].save()

        return HttpResponseRedirect('/tasks')

    def get_step_url(self, step):
        return reverse(self.url_name, kwargs={'step':step})

// urls.py

from django.conf.urls import url 
from .views import CreateTaskView, TaskDetailView
from . import views
from .forms import ChooseSubcategoryForm, SetAddressForm, AddTaskDetailsForm


app_name='tasks'

named_task_forms = (
    ("subcategory", ChooseSubcategoryForm),
    ("address", SetAddressForm),
    ("task-details", AddTaskDetailsForm),
)

task_wizard = views.AddTaskWizard.as_view(named_task_forms, url_name="task_step")

urlpatterns = [

    url(r'^add_task/(?P<step>\w+)/$', task_wizard, name='task_step'),
]

// step1.html => subcategory form

<div class="row" id="create-task-progress">
    <div class="container">
        <div class="col-md-4 section-static border-top-gray text-center">
            <span class="glyphicon glyphicon-search glyphicon-md orange" ></span> <span class="orange">1. Choose Subcategory</span>
        </div>
        <div class="col-md-4 section-static col-middle text-center">
            <span class="glyphicon glyphicon-home glyphicon-md" ></span> <span>2. Set Address</span>
        </div>
        <div class="col-md-4 section-static border-top-gray text-center">
            <span class="glyphicon glyphicon-pencil glyphicon-md"></span> <span>3. Task Details</span>
        </div>
    </div>
</div>
<div class="row section-light-gray border-top-gray">
    <div class="container" id="task-form-container">
        <div class="col-md-12">
            <form action="{% url 'tasks:task_step' wizard.steps.current %}" method="POST" enctype="multipart/form-data" class="col-md-10 col-md-push-1">
                {% csrf_token %}
                {{ wizard.management_form }}
                <div class="col-md-12 task-field-container">
                    {{ wizard.form.subcategory.label }}
                    {{ wizard.form.subcategory }}
                </div>
                <input type="submit" value="Continue" id="add_task" class="btn btn-primary col-xs-12" />
            </form>
        </div>
    </div>
</div>

Solution

  • Based on what I see in your template, you're using url namespaces. I believe you need to change

    task_wizard = views.AddTaskWizard.as_view(named_task_forms, url_name="task_step")
    

    to

    task_wizard = views.AddTaskWizard.as_view(named_task_forms, url_name="tasks:task_step")
    

    So you're just missing the tasks: