Crispy Forms:用于拆分表单/两列相同模型的 FormHelper
Crispy Forms: FormHelper for split forms / two columns same model
我的模板分为两栏。
我只有一个模型,但旨在将表格分成两部分,第一列中的一部分,第二列中的另一部分。我的目标是将 FormHelper 用于 Crispy Forms。
可用的文档给出了一个神秘的提示,但没有任何示例,这样的解释尝试有点短。
https://django-crispy-forms.readthedocs.io/en/d-0/tags.html#rendering-several-forms-with-helpers
Rendering several forms with helpers
Often we get asked: “How do you render two or more forms, with their
respective helpers, using {% crispy %} tag, without having tags
rendered twice?” Easy, you need to set form_tag helper property to
False in every helper:
self.helper.form_tag = False
Then you will have to write a little of html code surrounding the
forms:
<form action="{% url submit_survey %}" class="uniForm" method="post">
{% crispy first_form %}
{% crispy second_form %}
</form>
更新: 这 post 解释了 Crispy 文档的内容
Define crispy forms context names for two forms in one
下面是我的代码。两个FormHelper把Model分成两部分,第一部分有字段:['car_model_make', 'status_is_secondhand']
第二部分字段:['seller', 'buyer']
我一直在寻找的是 "call" 在特定 {% crispy form %}
上的方法。给定 "help" 文档”,这样的 {% crispy product-modelform_1 %}
和 {% crispy product-modelform_2 %}
是行不通的。
# models.py
class Product(models.Models):
car_model_make = models.CharField(default='B', max_length=1, blank=True, choices=CAR_TYPE)
status_is_secondhand = models.BooleanField(blank=True)
seller = models.CharField(max_length=50, blank=True, choices=SELLER_TYPE)
buyer = models.CharField(max_length=50, blank=True, choices=BUYER_TYPE)
# forms.py
class ProductForm(ModelForm):
class Meta:
model = Product
fields = ('__all__')
def __init__(self, *args, **kwargs):
super(ProductForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-sm-4'
self.helper.field_class = 'col-sm-8'
self.helper.form_id = 'product-modelform'
self.helper.form_tag = False
model = 'car_model_make'
secondhand = 'status_is_secondhand'
self.fields[model].label = "Model"
self.fields[secondhand].label = "Is Secondhand"
self.helper.layout = Layout(
Field(model),
Field(secondhand),
)
def __init__(self, *args, **kwargs):
super(ProductForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-sm-4'
self.helper.field_class = 'col-sm-8'
self.helper.form_id = 'product-modelform'
self.helper.form_tag = False
seller = 'seller'
buyer = 'buyer'
self.fields[seller].label = "Seller"
self.fields[buyer].label = "buyer"
self.helper.layout = Layout(
Field(seller),
Field(buyer),
)
# views.py
class ProductFormView(FormView):
form_class = ProductForm
def form_valid(self, form):
form.save()
return super().form_valid(form)
def get_success_url(self):
return reverse('index')
# urls.py
urlpatterns = [
path('', index, name='index'),
path('product/', ProductFormView.as_view(template_name='product/product.html'),
# html template
{% extends "product/base.html" %}
{% load crispy_forms_tags %}
{% block col8_content %}
<form id="product-modelform" method="post">
{% csrf_token %}
{% crispy form %}
{% endblock col8_content %}
{% block col4_content %}
</form>
{% endblock col4_content %}
<input type="submit" value="Submit">
你不能有两个 __init__
方法,你实际上也不需要它。您可以在 FormHelper() 的帮助下将这两个 'columns' 包含在两个单独的 <div>
标签中。
def __init__(self, *args, **kwargs):
super(ProductForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-sm-4'
self.helper.field_class = 'col-sm-8'
self.helper.form_id = 'product-modelform'
self.helper.form_tag = False
self.helper.layout = Layout(
Div(
Div('car_model_make','status_is_secondhand', css_class='col-lg-6 col-md-6 col-sm-12'),
Div('seller','buyer', css_class='col-lg-6 col-md-6 col-sm-12'),
css_class='row'
)
)
希望,这给了你诀窍。参考 Layouts 了解更多。
这似乎暂时有效(主要受到 Define crispy forms context names for two forms in one 的启发,但在这里我创建了两个基于 ModelForm 的新表单):我希望我自己能更好地理解该解决方案,但至少它可以作为打算。
# models.py
class Product(models.Models):
car_model_make = models.CharField(default='B', max_length=1, blank=True, choices=CAR_TYPE)
status_is_secondhand = models.BooleanField(blank=True)
seller = models.CharField(max_length=50, blank=True, choices=SELLER_TYPE)
buyer = models.CharField(max_length=50, blank=True, choices=BUYER_TYPE)
# forms.py
class ProductForm(ModelForm):
class Meta:
model = Product
fields = ('__all__')
class CarForm(ProductForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-sm-4'
self.helper.field_class = 'col-sm-8'
self.helper.form_tag = False
self.helper.add_input(Submit('submit', 'Submit'))
model = 'car_model_make'
secondhand = 'status_is_secondhand'
self.fields[model].label = "Model"
self.fields[secondhand].label = "Is Secondhand"
self.helper.layout = Layout(
Field(model),
Field(secondhand),
)
class TransactionForm(ProductForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-sm-4'
self.helper.field_class = 'col-sm-8'
self.helper.form_tag = False
seller = 'seller'
buyer = 'buyer'
self.fields[seller].label = "Seller"
self.fields[buyer].label = "buyer"
self.helper.layout = Layout(
Field(Seller),
Field(buyer),
)
# views.py
class ProductFormView(FormView):
form_class = CarForm
model = Product
def get_context_data(self, **kwargs):
context = super(ProductFormView, self).get_context_data(**kwargs)
context['form_2'] = TransactionForm(instance=self.model())
return context
def form_valid(self, form):
self.object = form.save()
return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form):
return self.render_to_response(
self.get_context_data(
form=form,
)
)
def get_success_url(self):
return reverse('index')
# urls.py
urlpatterns = [
path('', index, name='index'),
path('product/', ProductFormView.as_view(template_name='product/product.html'),
# html template
{% extends "product/base.html" %}
{% load crispy_forms_tags %}
{% block col8_content %}
<form id="product-modelform" method="post">
{% csrf_token %}
{% crispy form %}
{% endblock col8_content %}
{% block col4_content %}
{% crispy form_2 %}
</form>
{% endblock col4_content %}
我的模板分为两栏。 我只有一个模型,但旨在将表格分成两部分,第一列中的一部分,第二列中的另一部分。我的目标是将 FormHelper 用于 Crispy Forms。
可用的文档给出了一个神秘的提示,但没有任何示例,这样的解释尝试有点短。
https://django-crispy-forms.readthedocs.io/en/d-0/tags.html#rendering-several-forms-with-helpers
Rendering several forms with helpers
Often we get asked: “How do you render two or more forms, with their respective helpers, using {% crispy %} tag, without having tags rendered twice?” Easy, you need to set form_tag helper property to False in every helper:
self.helper.form_tag = False
Then you will have to write a little of html code surrounding the forms:
<form action="{% url submit_survey %}" class="uniForm" method="post"> {% crispy first_form %} {% crispy second_form %} </form>
更新: 这 post 解释了 Crispy 文档的内容 Define crispy forms context names for two forms in one
下面是我的代码。两个FormHelper把Model分成两部分,第一部分有字段:['car_model_make', 'status_is_secondhand']
第二部分字段:['seller', 'buyer']
我一直在寻找的是 "call" 在特定 {% crispy form %}
上的方法。给定 "help" 文档”,这样的 {% crispy product-modelform_1 %}
和 {% crispy product-modelform_2 %}
是行不通的。
# models.py
class Product(models.Models):
car_model_make = models.CharField(default='B', max_length=1, blank=True, choices=CAR_TYPE)
status_is_secondhand = models.BooleanField(blank=True)
seller = models.CharField(max_length=50, blank=True, choices=SELLER_TYPE)
buyer = models.CharField(max_length=50, blank=True, choices=BUYER_TYPE)
# forms.py
class ProductForm(ModelForm):
class Meta:
model = Product
fields = ('__all__')
def __init__(self, *args, **kwargs):
super(ProductForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-sm-4'
self.helper.field_class = 'col-sm-8'
self.helper.form_id = 'product-modelform'
self.helper.form_tag = False
model = 'car_model_make'
secondhand = 'status_is_secondhand'
self.fields[model].label = "Model"
self.fields[secondhand].label = "Is Secondhand"
self.helper.layout = Layout(
Field(model),
Field(secondhand),
)
def __init__(self, *args, **kwargs):
super(ProductForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-sm-4'
self.helper.field_class = 'col-sm-8'
self.helper.form_id = 'product-modelform'
self.helper.form_tag = False
seller = 'seller'
buyer = 'buyer'
self.fields[seller].label = "Seller"
self.fields[buyer].label = "buyer"
self.helper.layout = Layout(
Field(seller),
Field(buyer),
)
# views.py
class ProductFormView(FormView):
form_class = ProductForm
def form_valid(self, form):
form.save()
return super().form_valid(form)
def get_success_url(self):
return reverse('index')
# urls.py
urlpatterns = [
path('', index, name='index'),
path('product/', ProductFormView.as_view(template_name='product/product.html'),
# html template
{% extends "product/base.html" %}
{% load crispy_forms_tags %}
{% block col8_content %}
<form id="product-modelform" method="post">
{% csrf_token %}
{% crispy form %}
{% endblock col8_content %}
{% block col4_content %}
</form>
{% endblock col4_content %}
<input type="submit" value="Submit">
你不能有两个 __init__
方法,你实际上也不需要它。您可以在 FormHelper() 的帮助下将这两个 'columns' 包含在两个单独的 <div>
标签中。
def __init__(self, *args, **kwargs):
super(ProductForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-sm-4'
self.helper.field_class = 'col-sm-8'
self.helper.form_id = 'product-modelform'
self.helper.form_tag = False
self.helper.layout = Layout(
Div(
Div('car_model_make','status_is_secondhand', css_class='col-lg-6 col-md-6 col-sm-12'),
Div('seller','buyer', css_class='col-lg-6 col-md-6 col-sm-12'),
css_class='row'
)
)
希望,这给了你诀窍。参考 Layouts 了解更多。
这似乎暂时有效(主要受到 Define crispy forms context names for two forms in one 的启发,但在这里我创建了两个基于 ModelForm 的新表单):我希望我自己能更好地理解该解决方案,但至少它可以作为打算。
# models.py
class Product(models.Models):
car_model_make = models.CharField(default='B', max_length=1, blank=True, choices=CAR_TYPE)
status_is_secondhand = models.BooleanField(blank=True)
seller = models.CharField(max_length=50, blank=True, choices=SELLER_TYPE)
buyer = models.CharField(max_length=50, blank=True, choices=BUYER_TYPE)
# forms.py
class ProductForm(ModelForm):
class Meta:
model = Product
fields = ('__all__')
class CarForm(ProductForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-sm-4'
self.helper.field_class = 'col-sm-8'
self.helper.form_tag = False
self.helper.add_input(Submit('submit', 'Submit'))
model = 'car_model_make'
secondhand = 'status_is_secondhand'
self.fields[model].label = "Model"
self.fields[secondhand].label = "Is Secondhand"
self.helper.layout = Layout(
Field(model),
Field(secondhand),
)
class TransactionForm(ProductForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-sm-4'
self.helper.field_class = 'col-sm-8'
self.helper.form_tag = False
seller = 'seller'
buyer = 'buyer'
self.fields[seller].label = "Seller"
self.fields[buyer].label = "buyer"
self.helper.layout = Layout(
Field(Seller),
Field(buyer),
)
# views.py
class ProductFormView(FormView):
form_class = CarForm
model = Product
def get_context_data(self, **kwargs):
context = super(ProductFormView, self).get_context_data(**kwargs)
context['form_2'] = TransactionForm(instance=self.model())
return context
def form_valid(self, form):
self.object = form.save()
return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form):
return self.render_to_response(
self.get_context_data(
form=form,
)
)
def get_success_url(self):
return reverse('index')
# urls.py
urlpatterns = [
path('', index, name='index'),
path('product/', ProductFormView.as_view(template_name='product/product.html'),
# html template
{% extends "product/base.html" %}
{% load crispy_forms_tags %}
{% block col8_content %}
<form id="product-modelform" method="post">
{% csrf_token %}
{% crispy form %}
{% endblock col8_content %}
{% block col4_content %}
{% crispy form_2 %}
</form>
{% endblock col4_content %}