如何在Django中执行多步骤表单?

时间:2021-11-04 12:49:28

I would like to create a mutli-step form in Django that only submits the data for processing at the end of all the steps. Each step needs to be able to access and display data that we entered in previous step(s).

我想在Django中创建一个多步骤表单,它只在所有步骤结束时提交数据以进行处理。每个步骤都需要能够访问和显示我们在上一步中输入的数据。

Is there a way to do this with Django? Django's Form-Wizard can't handle this basic functionality.

有没有办法用Django做到这一点? Django的Form-Wizard无法处理这个基本功能。

2 个解决方案

#1


17  

Of course there's a way to do this in Django.

当然,在Django中有一种方法可以做到这一点。

One way is to hold your values in session until you submit them at the end. You can populate your forms using values held in session if you return to previous step.

一种方法是将值保存在会话中,直到最后提交它们为止。如果返回上一步,则可以使用会话中保存的值填充表单。

With some searching, you may find an app that someone has already written that will do what you want, but doing what you need isn't hard to do with Django, or any other framework.

通过一些搜索,您可能会发现一个已经编写过的应用程序可以执行您想要的操作,但是使用Django或任何其他框架来做您需要的并不难。

Example, ignoring import statements:

例如,忽略import语句:

#models/forms

class Person(models.Model):
    fn = models.CharField(max_length=40)

class Pet(models.Model):
    owner = models.ForeignKey(Person)
    name = models.CharField(max_length=40)

class PersonForm(forms.ModelForm):
    class Meta:
        model = Person

class PetForm(forms.ModelForm):
    class Meta:
        model = Pet
        exclude = ('owner',)

#views
def step1(request):
    initial={'fn': request.session.get('fn', None)}
    form = PersonForm(request.POST or None, initial=initial)
    if request.method == 'POST':
        if form.is_valid():
            request.session['fn'] = form.cleaned_data['fn']
            return HttpResponseRedirect(reverse('step2'))
    return render(request, 'step1.html', {'form': form})

def step2(request):
    form = PetForm(request.POST or None)
    if request.method == 'POST':
        if form.is_valid():
            pet = form.save(commit=False)
            person = Person.objects.create(fn=request.session['fn'])
            pet.owner = person
            pet.save()
            return HttpResponseRedirect(reverse('finished'))
    return render(request, 'step2.html', {'form': form})

We'll assume that step2.html has a link to go back to step1.html.

我们假设step2.html有一个链接可以回到step1.html。

You'll notice in the step1 view I'm pulling the value for fn from session that was set when the form was saved. You would need to persist the values from all previous steps into the session. At the end of the steps, grab the values, create your objects and redirect to a finished view, whatever that might be.

您将在step1视图中注意到我从保存表单时设置的会话中提取fn的值。您需要将所有先前步骤中的值保留到会话中。在步骤结束时,抓取值,创建对象并重定向到完成的视图,无论可能是什么。

None of this code has been tested, but it should get you going.

这些代码都没有经过测试,但它应该让你前进。

#2


12  

You can easily do this with the form wizard of django-formtools. A simple example would be something like the following.

您可以使用django-formtools的表单向导轻松完成此操作。一个简单的例子如下。

forms.py

forms.py

from django import forms

class ContactForm1(forms.Form):
    subject = forms.CharField(max_length=100)
    sender = forms.EmailField()

class ContactForm2(forms.Form):
    message = forms.CharField(widget=forms.Textarea)

views.py

views.py

from django.shortcuts import redirect
from formtools.wizard.views import SessionWizardView

class ContactWizard(SessionWizardView):
    def done(self, form_list, **kwargs):
        do_something_with_the_form_data(form_list)
        return redirect('/page-to-redirect-to-when-done/')

urls.py

urls.py

from django.conf.urls import url

from forms import ContactForm1, ContactForm2
from views import ContactWizard

urlpatterns = [
    url(r'^contact/$', ContactWizard.as_view([ContactForm1, ContactForm2])),
]

#1


17  

Of course there's a way to do this in Django.

当然,在Django中有一种方法可以做到这一点。

One way is to hold your values in session until you submit them at the end. You can populate your forms using values held in session if you return to previous step.

一种方法是将值保存在会话中,直到最后提交它们为止。如果返回上一步,则可以使用会话中保存的值填充表单。

With some searching, you may find an app that someone has already written that will do what you want, but doing what you need isn't hard to do with Django, or any other framework.

通过一些搜索,您可能会发现一个已经编写过的应用程序可以执行您想要的操作,但是使用Django或任何其他框架来做您需要的并不难。

Example, ignoring import statements:

例如,忽略import语句:

#models/forms

class Person(models.Model):
    fn = models.CharField(max_length=40)

class Pet(models.Model):
    owner = models.ForeignKey(Person)
    name = models.CharField(max_length=40)

class PersonForm(forms.ModelForm):
    class Meta:
        model = Person

class PetForm(forms.ModelForm):
    class Meta:
        model = Pet
        exclude = ('owner',)

#views
def step1(request):
    initial={'fn': request.session.get('fn', None)}
    form = PersonForm(request.POST or None, initial=initial)
    if request.method == 'POST':
        if form.is_valid():
            request.session['fn'] = form.cleaned_data['fn']
            return HttpResponseRedirect(reverse('step2'))
    return render(request, 'step1.html', {'form': form})

def step2(request):
    form = PetForm(request.POST or None)
    if request.method == 'POST':
        if form.is_valid():
            pet = form.save(commit=False)
            person = Person.objects.create(fn=request.session['fn'])
            pet.owner = person
            pet.save()
            return HttpResponseRedirect(reverse('finished'))
    return render(request, 'step2.html', {'form': form})

We'll assume that step2.html has a link to go back to step1.html.

我们假设step2.html有一个链接可以回到step1.html。

You'll notice in the step1 view I'm pulling the value for fn from session that was set when the form was saved. You would need to persist the values from all previous steps into the session. At the end of the steps, grab the values, create your objects and redirect to a finished view, whatever that might be.

您将在step1视图中注意到我从保存表单时设置的会话中提取fn的值。您需要将所有先前步骤中的值保留到会话中。在步骤结束时,抓取值,创建对象并重定向到完成的视图,无论可能是什么。

None of this code has been tested, but it should get you going.

这些代码都没有经过测试,但它应该让你前进。

#2


12  

You can easily do this with the form wizard of django-formtools. A simple example would be something like the following.

您可以使用django-formtools的表单向导轻松完成此操作。一个简单的例子如下。

forms.py

forms.py

from django import forms

class ContactForm1(forms.Form):
    subject = forms.CharField(max_length=100)
    sender = forms.EmailField()

class ContactForm2(forms.Form):
    message = forms.CharField(widget=forms.Textarea)

views.py

views.py

from django.shortcuts import redirect
from formtools.wizard.views import SessionWizardView

class ContactWizard(SessionWizardView):
    def done(self, form_list, **kwargs):
        do_something_with_the_form_data(form_list)
        return redirect('/page-to-redirect-to-when-done/')

urls.py

urls.py

from django.conf.urls import url

from forms import ContactForm1, ContactForm2
from views import ContactWizard

urlpatterns = [
    url(r'^contact/$', ContactWizard.as_view([ContactForm1, ContactForm2])),
]