Reputation: 3940
I wanted to make a Django contact form on website and I found Django crispy forms very useful for that, but it turned out that I can't mix it with Django FormView just like this. Crispy forms have done awesome job in front-end layout, but I can't grab any information from the filled form to my Django app. I've tried this tutorial: Simple Django email form using CBV, but it's outdated and is not helpful at all. Here are my forms.py:
from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
class ContactForm(forms.Form):
name = forms.CharField(
label = "Name:",
max_length = 80,
required = True,
)
email = forms.CharField(
label = "E-mail:",
max_length = 80,
required = True,
)
subject = forms.CharField(
label = "Subject:",
max_length = 80,
required = True,
)
message = forms.CharField(
widget = forms.Textarea,
label = "Message:",
required = True,
)
def __init__(self, *args, **kwargs):
super(ContactForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.add_input(Submit('send', 'Send'))
views.py:
from django.shortcuts import render
from myapp.forms import ContactForm
from django.core.mail import send_mail
from django.views.generic.edit import FormView
class ContactFormView(FormView):
form_class = ContactForm
template_name = "myapp/contact.html"
success_url = '/email_sent/'
def form_valid(self, form):
message = "{name} / {email} said: ".format(
name=form.cleaned_data.get('name'),
email=form.cleaned_data.get('email'))
message += "\n\n{0}".format(form.cleaned_data.get('message'))
send_mail(
subject=form.cleaned_data.get('subject').strip(),
message=message,
from_email='[email protected]',
recipient_list=['[email protected]'],
)
return super(ContactFormView, self).form_valid(form)
def contact(request):
contact_form = ContactFormView()
return render(request, 'myapp/contact.html', {'contact_form': contact_form})
and my template contact.html:
{% extends "layout.html" %}
{% load crispy_forms_tags %}
{% block title %}Contact{% endblock %}
{% block content %}
<h2><b>Contact</b></h2>
<div class="container">
<p>You can e-mail me at: <a href="mailto:[email protected]">[email protected]</a></p>
<br>
<p>Or simply fill the form below:</p>
<br>
{% crispy contact_form %}
</div>
{% endblock %}
What I get is:
Exception Type: TypeErrorException Value:
'ContactFormView' object is not iterable
Any suggestions how to use Django crispy forms with Django FormView?
Upvotes: 2
Views: 2151
Reputation: 308899
This doesn't have anything to do with crispy forms. The problem is in this piece of code, where you are treating ContactFormView
as if it's a form.
def contact(request):
contact_form = ContactFormView()
return render(request, 'myapp/contact.html', {'contact_form': contact_form})
However, ContactFormView
is not a form, it's a class based view. You don't need to define another view contact
, you already have a view ContactFormView
.
Change your url pattern to use the class based view:
url(r'^contact/$', ContactFormView.as_view(), name='contact')
Then in your template, include the form with:
{{ form }}}
Once the view is working with regular forms, use the crispy tag so that it is styled as you wish:
{% crispy form %}
Upvotes: 3