用1个按钮Django提交2个自定义的Crispy表单



我有两个表单,第二个表单引用了第一个表单。我可以使用脆表单正确执行表单,但是,当我使用helper=FormHelp((自定义每个表单时,它们将不再一起提交。本质上,一个表单被提交,而另一个表单认为它缺少所有输入数据。

Forms.py

from django.forms import ModelForm, forms
from .models import Item, Item_dimensions
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Submit, Row, Column

# Create the form class.
class List_Item_Form(ModelForm):
class Meta:
model = Item
exclude = ('id','creator','created_on','updated_on' )
helper = FormHelper()
helper.layout = Layout(
Row(
Column('item_name', css_class='form-group col-md-6 mb-0'),
Column('price', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
'short_description',
'description',
Row(
Column('main_image', css_class='form-group col-md-2.5 mb-0'),
Column('image_2', css_class='form-group col-md-2.5 mb-0'),
Column('image_3', css_class='form-group col-md-2.5 mb-0'),
Column('image_4', css_class='form-group col-md-2.5 mb-0'),
Column('image_5', css_class='form-group col-md-2.5 mb-0'),
css_class='form-row'
),
'quantity'
)
helper.add_input(Submit('submit', 'Submit', css_class='btn-primary'))
helper.form_method = 'POST'
class List_Item_Dimensions(ModelForm):
class Meta:
model = Item_dimensions
exclude = ('id','item_id')
helper = FormHelper()
helper.layout = Layout(
Row(
Column('x_dim_mm', css_class='form-group col-md-4 mb-0'),
Column('y_dim_mm', css_class='form-group col-md-4 mb-0'),
Column('z_dim_mm', css_class='form-group col-md-4 mb-0'),
css_class='form-row'
),
'weight_grams',
Submit('submit', 'add_listing')
)
helper.add_input(Submit('submit', 'Submit', css_class='btn-primary'))
helper.form_method = 'POST'

我已尝试删除

helper.add_input(Submit(‘Submit’,‘Submit’,css_class=‘tn-primary’(

只使用一个提交按钮,但它不起作用

Views.py

@login_required
def AddListing(request):
if request.method == 'POST':
form = List_Item_Form(request.POST,request.FILES)
dim_form = List_Item_Dimensions(request.POST)
if form.is_valid() and dim_form.is_valid():
itemName = form.cleaned_data['item_name']
price = form.cleaned_data['price']
s_desc = form.cleaned_data['short_description']
desc = form.cleaned_data['description']
quantity = form.cleaned_data['quantity']
main_img = form.cleaned_data['main_image']
image_2 = form.cleaned_data['image_2']
image_3 = form.cleaned_data['image_3']
image_4 = form.cleaned_data['image_4']
image_5 = form.cleaned_data['image_5']
x_dim = dim_form.cleaned_data['x_dim_mm']
y_dim = dim_form.cleaned_data['y_dim_mm']
z_dim = dim_form.cleaned_data['z_dim_mm']
weight = dim_form.cleaned_data['weight_grams']
current_user =  request.user

model_instance = Item(creator=current_user, item_name=itemName, 
price=price,short_description=s_desc,
description=desc, quantity=quantity,
main_image=main_img, image_2=image_2, 
image_3=image_3, image_4 = image_4, 
image_5=image_5)
dim_instance = Item_dimensions(x_dim_mm = x_dim,
y_dim_mm =y_dim,
z_dim_mm =z_dim, 
weight_grams = weight)
model_instance.save()
# dim_instance.save(commit=False)
dim_instance.item_id = model_instance
dim_instance.save()
return HttpResponseRedirect('/user_profile/items/')
else:
form = List_Item_Form()
dim_form = List_Item_Dimensions()
return render(request, 'store/add_listing.html', {'form': form,'dim_form':dim_form})

template.html

{% block content %}
<div>
<h1> list a new item </h1>
{% load crispy_forms_tags %} 
{% csrf_token %}
<form method="post", enctype="multipart/form-data">{% csrf_token %}
{% crispy form  %}
{% crispy dim_form %}
{% comment %} {{ form|crispy }}
{{ dim_form|crispy }} {% endcomment %}
<input name="submit" type="post" value="template button">
</form>
</div>
{% endblock content %}

{% crispy form %}会自动添加<form></form>标记,除非您另外指定form_tag = False。看见https://django-crispy-forms.readthedocs.io/en/latest/form_helper.html

在这里,您已经给出了一个外部标记,因此它内部的crispy标记将创建嵌套表单。这会使您的HTML无效。检查https://django-crispy-forms.readthedocs.io/en/latest/crispy_tag_forms.html#crispy-标签形式

PS:(最近没有使用django(-你不需要在构造函数中包含helper和其他自定义吗?

扩展@art的答案,以下是您可能想要的:

from django.forms import ModelForm
from .models import Item, Item_dimensions
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Submit, Row, Column

# Create the form class.
class List_Item_Form(ModelForm):
class Meta:
model = Item
exclude = ('id', 'creator', 'created_on', 'updated_on')
helper = FormHelper()
helper.layout = Layout(
Row(
Column('item_name', css_class='form-group col-md-6 mb-0'),
Column('price', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
'short_description',
'description',
Row(
Column('main_image', css_class='form-group col-md-2.5 mb-0'),
Column('image_2', css_class='form-group col-md-2.5 mb-0'),
Column('image_3', css_class='form-group col-md-2.5 mb-0'),
Column('image_4', css_class='form-group col-md-2.5 mb-0'),
Column('image_5', css_class='form-group col-md-2.5 mb-0'),
css_class='form-row'
),
'quantity'
)
helper.add_input(Submit('submit', 'Submit', css_class='btn-primary'))
helper.form_tag = False  # add this
helper.disable_csrf = True  # otherwise the crispy form will add an additional csrf token (optional)

class List_Item_Dimensions(ModelForm):
class Meta:
model = Item_dimensions
exclude = ('id', 'item_id')
helper = FormHelper()
helper.layout = Layout(
Row(
Column('x_dim_mm', css_class='form-group col-md-4 mb-0'),
Column('y_dim_mm', css_class='form-group col-md-4 mb-0'),
Column('z_dim_mm', css_class='form-group col-md-4 mb-0'),
css_class='form-row'
),
'weight_grams',
Submit('submit', 'add_listing')
)
helper.add_input(Submit('submit', 'Submit', css_class='btn-primary'))
helper.form_tag = False  # add this
helper.disable_csrf = True  # otherwise the crispy form will add an additional csrf token (optional)

你可以用同样的方式在模板中渲染它们:

{% block content %}
<div>
<h1> list a new item </h1>
{% load crispy_forms_tags %}
<form method="post", enctype="multipart/form-data">{% csrf_token %}
{% crispy form  %}
{% crispy dim_form %}
<input name="submit" type="post" value="template button">
</form>
</div>
{% endblock content %}

还要注意,添加{%csrf_token%}只需添加一个类似于以下内容的附加隐藏表单字段:

<input type="hidden" name="csrfmiddlewaretoken" value="uo5TUfy6PxVbDDKuEhRlJEri3wGOkOZuuZbHKoDWGOhA1O5zjk9RLSwfFcEuxQec">

添加额外的csrf令牌没有坏处,但也没有必要。

虽然与最初的问题没有严格的关系,但我也想提一点建议。在处理ModelForms时,Django在幕后做了很多魔术。这意味着,您可以省去手动获取视图中所有模型字段以创建新模型实例的麻烦。我还没有测试过,但你的观点很可能会被大大简化为类似的东西:

@login_required
def AddListing(request):
if request.method == 'POST':
form = List_Item_Form(request.POST,request.FILES)
dim_form = List_Item_Dimensions(request.POST)
if form.is_valid() and dim_form.is_valid():
current_user = request.user
model_instance = form.save(commit=False)
model_instance.creator = current_user
model_instance.save()
dim_instance = dim_form.save(commit=False)
dim_instance.item_id = model_instance
dim_instance.save()
return HttpResponseRedirect('/user_profile/items/')
else:
form = List_Item_Form()
dim_form = List_Item_Dimensions()
return render(request, 'store/add_listing.html', {'form': form, 'dim_form': dim_form})

最新更新