gpt4 book ai didi

python - 如何在表单向导中使用 ModelFormSet

转载 作者:行者123 更新时间:2023-11-28 22:46:48 27 4
gpt4 key购买 nike

Django 文档没有很好地记录这个主题。事实上,他们在文档中唯一的引用是这一段:

How to work with ModelForm and ModelFormSet

WizardView.instance_dict. WizardView supports ModelForms and ModelFormSets. Additionally to initial_dict, the as_view() >method takes an instance_dict argument that should contain model instances for steps based on >ModelForm and querysets for steps based on ModelFormSet.

我还没有找到关于如何使用它的任何好的和清晰的例子。有人可以帮我解决这个问题吗?

具体来说:

  • 在 forms.py 中做什么?
  • 如果我只在表单的某些步骤而不是所有步骤中需要 ModelFormSet 怎么办?
  • 我需要在 views.py 和模板中做什么?

以我正在做的一个用例和小项目为例,我分享了我的代码:

  • 用例:
    • 用户想要以多步形式注册,第一步他介绍他的名字和姓氏。
  • 在第二步中,他介绍了他的护照号码和酒店登记,他还想登记他的儿子和妻子,他们将和他一起去这家酒店(这里我想使用 HotelRegistration 模型中的 modelformset)。
  • 在第三步中,他输入了他的航类信息。如果表单有效并保存在数据库中,则会收到一条确认消息。

这是我的代码:

模型.py

class Event(models.Model):

name = models.CharField(max_length=100)
date_from = models.DateField(auto_now=False)
date_to = models.DateField(auto_now=False)
description = models.TextField()

def __unicode__(self):
return self.name


class Hotel(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=100)

def __unicode__(self):
return self.name


class HotelRegistration(models.Model):
pax_first_name = models.CharField(max_length=50)
pax_last_name = models.CharField(max_length=50)
hotel = models.ForeignKey(Hotel)

def __unicode__(self):
return self.pax_first_name


class Registration(models.Model):

first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
passport = models.CharField(max_length=15)
city_origin = models.CharField(max_length=50)
flight_date_from = models.DateField(auto_now=False)
flight_date_to = models.DateField(auto_now=False)
require_transfer = models.BooleanField(default=None)
event = models.ForeignKey(Event)
hotel_registration = models.ForeignKey(HotelRegistration, blank=True, null=True)

def __unicode__(self):
return self.first_name

表单.py

from django import forms

from .models import Registration

class FormStep1(forms.ModelForm):
class Meta:
model = Registration
fields = ['first_name', 'last_name']
widgets = {
'first_name': forms.TextInput(attrs={'placeholder': 'Nombre de la persona que esta reservando', 'label_tag': 'Nombre'}),
'last_name': forms.TextInput(attrs={'placeholder': 'Apellido'})
}

class FormStep2(forms.ModelForm):
class Meta:
model = Registration
fields = ['passport', 'hotel_registration']
exclude = ('first_name', 'last_name', 'event' , 'city_origin', 'flight_date_from', 'flight_date_to', 'require_transfer')
widgets = {
'passport': forms.NumberInput(attrs={'placeholder':'Escriba su pasaporte'})
}

class FormStep3(forms.ModelForm):
class Meta:
model = Registration
fields = ['city_origin', 'flight_date_from', 'flight_date_to', 'require_transfer', 'event']
exclude = ('first_name', 'last_name', 'hotel_registration')
widgets = {
'city_origin': forms.TextInput(attrs={'placeholder':'Ciudad desde donde esta viajando'}),
'flight_date_from': forms.DateInput(format=('%d-%m-%Y'), attrs={'class':'myDateClass', 'placeholder':'Select a date'}),
'flight_date_to': forms.DateInput(format=('%d-%m-%Y'), attrs={'class':'myDateClass', 'placeholder':'Select a date'}),
'require_transfer': forms.Select(),
'event': forms.Select()
}

View .py

from django.shortcuts import render
from django.contrib.formtools.wizard.views import SessionWizardView
from django.http import HttpResponseRedirect
from django.views.generic import TemplateView
from django.forms.models import inlineformset_factory

from .models import Registration, HotelRegistration
from .forms import FormStep1, FormStep2, FormStep3


FORMS = [
("step1", FormStep1),
("step2", FormStep2),
("step3", FormStep3)
]

TEMPLATES = {
"step1" : "wizard/step1.html",
"step2" : "wizard/step2.html",
"step3" : "wizard/step3.html"
}


class TestFormWizard(SessionWizardView):

instance = None

def get_form_instance(self, step):
if self.instance is None:
self.instance = Registration()
return self.instance


def get_form(self, step=None, data=None, files=None):
form = super(TestFormWizard, self).get_form(step, data, files)
HotelRegistFormSet = inlineformset_factory(HotelRegistration, Registration, can_delete=True, extra=1)

# determine the step if not given
if step is None:
step = self.steps.current

if step == '2':
hotel_registration_formset = HotelRegistFormSet(self.steps.current, self.steps.files, prefix="step2")
return form


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

def done(self, form_list, **kwargs):
self.instance.save()
return HttpResponseRedirect('/register/confirmation')


class ConfirmationView(TemplateView):
template_name = 'wizard/confirmation.html'

模板

   {% extends "base.html" %}
{% load i18n %}


{% 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 %}

最佳答案

在 forms.py 中做什么?

覆盖 SessionWizardView 的 get_form_instance 方法。这是 FormWizard 用来确定模型实例是否与模型表单一起使用的方法

WizardView.get_form_instance(步骤)仅当 ModelForm 用作 step 步骤的表单时,才会调用此方法。返回一个 Model 对象,在为 step 步骤实例化 ModelForm 时,该对象将作为实例参数传递。如果在初始化表单向导时没有提供实例对象,将返回 None。

这可以在 SessionWizardView 实现中按步骤有条件地完成。我不明白你想做什么,无法给你一个确切的例子,所以这里有一个更通用的例子。

def get_form_instance(self, step):
if step == u'3':
past_data = self.get_cleaned_data_for_step(u'2')
hotel_name = past_data['hotel_field']
hotel = Hotel.objects.get(name=hotel_name)
return hotel #do NOT set self.instance, just return the model instance you want
return self.instance_dict.get(step, None) # the default implementation

如果我只在表单的某些步骤而不是所有步骤中需要 ModelFormSet 怎么办?

见上;使用“if step == (form/step name)”表达式来确定每一步发生的事情。

我需要在 views.py 和模板中做什么?

使用 ModelForm 并向其传递模型对象实例将设置初始表单值。你需要更多吗?

希望这向您展示了 FormWizard 中预期的结构。与我使用过的 Django 的任何其他部分相比,FormWizard 需要非常特殊的结构并且是一个整体类。

关于python - 如何在表单向导中使用 ModelFormSet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27070936/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com