自定义模板在 django formtools 中不起作用
custom template not working in django formtools
我一直在尝试使用 formtools 向导在我的 Django 应用程序中添加多页表单。我需要为每个步骤设置自定义表单。总共有2个步骤。这是我的代码:
views.py
TEMPLATES = {"initial": "my_app/form_initial.html",
"final": "my_app/form_last.html"}
class ModelCreateView(SessionWizardView):
model = MyModel
template_name = "my_app/model_form.html"
file_storage =
FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'custom'))
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
my_app/model_form.html
{% extends "my_app/base.html" %}
{% block extra_css %}
{{ wizard.form.media }}
{% endblock %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
{{ wizard.management_form }}
<h1>{{ wizard }}</h1>
{% if wizard.form.forms %}
<h1>{{ wizard.form.forms }}</h1>
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
<input type="submit" value="submit"/>
</form>
{% endblock content %}
my_app/form_initial.html
<-- custom form template for step 1 -->
my_app/form_last.html
<-- custom form template for step 2 -->
如果我理解正确,自定义表单模板将取代
{{ form }}
正在调用的基本模板中的标记(my_app/model_form.html)。
我的问题是,使用当前代码,直接调用 my_app/form_initial.html。
此外,如果我尝试仅包括
{{ wizard.management_form }}
在 my_app/form_initial.html 中并附上必要的表单元素,在提交时,它只是重新加载当前页面而不是将我带到 my_app/form_last.html
请告诉我我做错了什么。
更新:我通过正确扩展基本表单模板解决了自定义模板的问题。但是现在当我提交第一步时,相同的步骤页面会重新加载而不是进入下一步。请告诉我如何调试它?
更新 2:我尝试进行更多调试并发现这一点,即使 post 请求包含字段,form.is_valid()
returns 假。 form.errors
表示所有字段都是 missing
我让向导在我的应用程序中使用额外的元组列表来映射表单。试试这个,看看它是否有效。
WIZARD_FORMS = [("initial", InitailFormName),
("final" , FinalFormName),
]
TEMPLATES = {"initial": "my_app/form_initial.html",
"final": "my_app/form_last.html"}
class ModelCreateView(SessionWizardView):
model = MyModel
template_name = "my_app/model_form.html"
file_storage =
FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'custom'))
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
我实现模板的方法有两个问题。
- 我原以为一旦在视图中定义了基本模板,自定义步骤表单模板就会被自己替换。执行此操作的正确方法是定义基本模板模板并在自定义步骤模板中扩展它。
例如:
base_form_template.html
{% block content %}
<form style="height:inherit;" action="" method="post">
{% csrf_token %}
{{ wizard.management_form }}
{{ wizard.form.errors}}
{{ wizard.form.non_field_errors}}
{% block custom_form %}
{% endblock %}
</form>
{% endblock content %}
step1.html
{% extends "my_app/base_form_template.html" %}
<-- custom form template code goes here -->
step2.html
{% extends "my_app/base_form_template.html" %}
<-- custom form template code goes here -->
- 在我的自定义表单模板中,输入字段的
name
属性需要设置为 wizard.form.<model_attribute>.html_name
。这很难找到。我最初只是将它设置为 wizard.form.<model_attribute>
并想知道为什么它不起作用。做了更多的挖掘,发现了这个。 html_name
与格式 <step_name>_<field_name>
不同。现在看来,起这样的名字确实有道理。
Keval 所说的是正确的 - 导致 self.cleaned_data['field']
为空的主要问题是我需要使用 form.field.html_name
而不是 form.field.name
作为模板的名称字段。
但是,从所提供的文档来看,这并不是那么清楚。这是我的模板页面的摘录,所以它更清楚:
<div class="form-group">
<label>{{ form.account_name.label }}</label>
<input name="{{ form.account_name.html_name }}"
value="{{ form.account_name.value|default_if_none:'' }}"
class="form-control">
</div>
我一直在尝试使用 formtools 向导在我的 Django 应用程序中添加多页表单。我需要为每个步骤设置自定义表单。总共有2个步骤。这是我的代码:
views.py
TEMPLATES = {"initial": "my_app/form_initial.html",
"final": "my_app/form_last.html"}
class ModelCreateView(SessionWizardView):
model = MyModel
template_name = "my_app/model_form.html"
file_storage =
FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'custom'))
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
my_app/model_form.html
{% extends "my_app/base.html" %}
{% block extra_css %}
{{ wizard.form.media }}
{% endblock %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
{{ wizard.management_form }}
<h1>{{ wizard }}</h1>
{% if wizard.form.forms %}
<h1>{{ wizard.form.forms }}</h1>
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
<input type="submit" value="submit"/>
</form>
{% endblock content %}
my_app/form_initial.html
<-- custom form template for step 1 -->
my_app/form_last.html
<-- custom form template for step 2 -->
如果我理解正确,自定义表单模板将取代
{{ form }}
正在调用的基本模板中的标记(my_app/model_form.html)。
我的问题是,使用当前代码,直接调用 my_app/form_initial.html。
此外,如果我尝试仅包括
{{ wizard.management_form }}
在 my_app/form_initial.html 中并附上必要的表单元素,在提交时,它只是重新加载当前页面而不是将我带到 my_app/form_last.html
请告诉我我做错了什么。
更新:我通过正确扩展基本表单模板解决了自定义模板的问题。但是现在当我提交第一步时,相同的步骤页面会重新加载而不是进入下一步。请告诉我如何调试它?
更新 2:我尝试进行更多调试并发现这一点,即使 post 请求包含字段,form.is_valid()
returns 假。 form.errors
表示所有字段都是 missing
我让向导在我的应用程序中使用额外的元组列表来映射表单。试试这个,看看它是否有效。
WIZARD_FORMS = [("initial", InitailFormName),
("final" , FinalFormName),
]
TEMPLATES = {"initial": "my_app/form_initial.html",
"final": "my_app/form_last.html"}
class ModelCreateView(SessionWizardView):
model = MyModel
template_name = "my_app/model_form.html"
file_storage =
FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'custom'))
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
我实现模板的方法有两个问题。
- 我原以为一旦在视图中定义了基本模板,自定义步骤表单模板就会被自己替换。执行此操作的正确方法是定义基本模板模板并在自定义步骤模板中扩展它。
例如:
base_form_template.html
{% block content %}
<form style="height:inherit;" action="" method="post">
{% csrf_token %}
{{ wizard.management_form }}
{{ wizard.form.errors}}
{{ wizard.form.non_field_errors}}
{% block custom_form %}
{% endblock %}
</form>
{% endblock content %}
step1.html
{% extends "my_app/base_form_template.html" %}
<-- custom form template code goes here -->
step2.html
{% extends "my_app/base_form_template.html" %}
<-- custom form template code goes here -->
- 在我的自定义表单模板中,输入字段的
name
属性需要设置为wizard.form.<model_attribute>.html_name
。这很难找到。我最初只是将它设置为wizard.form.<model_attribute>
并想知道为什么它不起作用。做了更多的挖掘,发现了这个。html_name
与格式<step_name>_<field_name>
不同。现在看来,起这样的名字确实有道理。
Keval 所说的是正确的 - 导致 self.cleaned_data['field']
为空的主要问题是我需要使用 form.field.html_name
而不是 form.field.name
作为模板的名称字段。
但是,从所提供的文档来看,这并不是那么清楚。这是我的模板页面的摘录,所以它更清楚:
<div class="form-group">
<label>{{ form.account_name.label }}</label>
<input name="{{ form.account_name.html_name }}"
value="{{ form.account_name.value|default_if_none:'' }}"
class="form-control">
</div>