Using Ajax in the django forms
Old Traditional Methods
Tip
# View
from django.views.generic import FormView, TemplateView
from django.urls import reverse_lazy
from django.core.exceptions import ObjectDoesNotExist
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect
from django.core.mail import send_mail
from .forms import ContactForm
from .models import ContactServiceCategory
class ContactView(FormView):
form_class = ContactForm
success_url = reverse_lazy('contact:success_url')
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
try:
initial_service = ContactServiceCategory.objects.get(id=1)
except ObjectDoesNotExist:
initial_service = None
kwargs['initial'] = {'service': initial_service}
return kwargs
@method_decorator(csrf_protect)
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
try:
form.save()
self.send_mail(form)
request.session['success_message'] = 'Your form was submitted successfully!'
return self.form_valid(form)
except Exception as e:
return self.handle_form_error(e)
else:
print("Invalid Form")
return self.form_invalid(form)
def handle_form_error(self, e):
print("Error saving form:", e)
return self.form_invalid(self.get_form())
def send_mail(self, form):
subject = 'New Contact Form Submission'
recipients = ['bishowthapa33@gmail.com']
message = f'Name: {form.cleaned_data["name"]}\nEmail: {form.cleaned_data["email"]}\nMessage: {form.cleaned_data["message"]}'
sender = form.cleaned_data["email"]
send_mail(subject, message, sender, recipients, fail_silently=True)
class ContactInnerView(TemplateView):
template_name = 'contact_us/contact.html'
class SuccessView(TemplateView):
template_name = 'contact_us/success.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['success_message'] = self.request.session.get('success_message')
return context
<div class="row">
<h5 class="col-md-12 mb-4" style="font-weight: bold; color: #f57d20;">Schedule your Meetings</h5>
</div>
<form action="{% url 'contact:contact' %}" method="post">
{% csrf_token %}
<div class="mb-3">
{{ form.name.label_tag }}
{{ form.name }}
{% if form.name.errors %}
<div class="text-danger">
{% for error in form.name.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
</div>
<div class="mb-3">
{{ form.email.label_tag }}
{{ form.email }}
{% if form.email.errors %}
<div class="text-danger">
{% for error in form.email.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
</div>
<div class="mb-3">
{{ form.message.label_tag }}
{{ form.message }}
{% if form.message.errors %}
<div class="text-danger">
{% for error in form.message.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
</div>
<div class="mb-3">
{{ form.service.label_tag }}
{{ form.service }}
{% if form.service.errors %}
<div class="text-danger">
{% for error in form.service.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
</div>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<div class="g-recaptcha" data-sitekey="6LezcbspAAAAAL6-lkWnexayFjQ3kK4R4wRixxpY"></div>
<button type="submit" class="btn btn-primary w-100 mt-4">Submit</button>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.full.min.js" integrity="sha512-RtZU3AyMVArmHLiW0suEZ9McadTdegwbgtiQl5Qqo9kunkVg1ofwueXD8/8wv3Af8jkME3DDe3yLfR8HSJfT2g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
$(document).ready(function() {
$('.ispl-form').select2({
placeholder: "Choose a service",
allowClear: true
});
});
</script>
Using Ajax
If you want to submit the contact form without redirecting to another page and avoid reloading the browser, you can use AJAX to handle the form submission asynchronously. This way, you can stay on the same page and display a success message or update the form accordingly.
Here's how you can achieve this using jQuery for the AJAX request:
1. Update the Contact Form Template:
Add an id
to your form to easily target it with jQuery. Also, include a div to display the success message.
<div class="row">
<h5 class="col-md-12 mb-4" style="font-weight: bold; color: #f57d20;">Schedule your Meetings</h5>
</div>
<form id="contactForm" method="post">
{% csrf_token %}
<div class="mb-3">
{{ form.name.label_tag }}
{{ form.name }}
{% if form.name.errors %}
<div class="text-danger">
{% for error in form.name.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
</div>
<div class="mb-3">
{{ form.email.label_tag }}
{{ form.email }}
{% if form.email.errors %}
<div class="text-danger">
{% for error in form.email.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
</div>
<div class="mb-3">
{{ form.message.label_tag }}
{{ form.message }}
{% if form.message.errors %}
<div class="text-danger">
{% for error in form.message.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
</div>
<div class="mb-3">
{{ form.service.label_tag }}
{{ form.service }}
{% if form.service.errors %}
<div class="text-danger">
{% for error in form.service.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
</div>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<div class="g-recaptcha" data-sitekey="6LezcbspAAAAAL6-lkWnexayFjQ3kK4R4wRixxpY"></div>
<button type="submit" class="btn btn-primary w-100 mt-4">Submit</button>
</form>
<div id="successMessage" class="alert alert-success mt-3" style="display:none;">
Your form was submitted successfully!
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894yeEpZTw1gyf9DZ9FZeiG0ct0tNEeR1Aq/wY1VoL5/6n6E0UVx7S9KK1T1WsvS8AwGiJw4nFBE1P4N3ggMBQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.full.min.js" integrity="sha512-RtZU3AyMVArmHLiW0suEZ9McadTdegwbgtiQl5Qqo9kunkVg1ofwueXD8/8wv3Af8jkME3DDe3yLfR8HSJfT2g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
$(document).ready(function() {
$('.ispl-form').select2({
placeholder: "Choose a service",
allowClear: true
});
$('#contactForm').on('submit', function(event) {
event.preventDefault();
$.ajax({
type: 'POST',
url: "{% url 'contact:contact' %}",
data: $(this).serialize(),
success: function(response) {
$('#successMessage').show();
$('#contactForm')[0].reset();
},
error: function(xhr, status, error) {
console.log("Error:", error);
}
});
});
});
</script>
2. Update the Contact View:
Ensure the view returns a JSON response for success and error scenarios.
from django.http import JsonResponse
class ContactView(FormView):
form_class = ContactForm
success_url = reverse_lazy('contact:success_url')
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
try:
initial_service = ContactServiceCategory.objects.get(id=1)
except ObjectDoesNotExist:
initial_service = None
kwargs['initial'] = {'service': initial_service}
return kwargs
@method_decorator(csrf_protect)
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
try:
form.save()
self.send_mail(form)
request.session['success_message'] = 'Your form was submitted successfully!'
return JsonResponse({'message': 'Your form was submitted successfully!'}, status=200)
except Exception as e:
return self.handle_form_error(e)
else:
return JsonResponse({'errors': form.errors}, status=400)
def handle_form_error(self, e):
return JsonResponse({'error': str(e)}, status=400)
def send_mail(self, form):
subject = 'New Contact Form Submission'
recipients = ['bishowthapa33@gmail.com']
message = f'Name: {form.cleaned_data["name"]}\nEmail: {form.cleaned_data["email"]}\nMessage: {form.cleaned_data["message"]}'
sender = form.cleaned_data["email"]
send_mail(subject, message, sender, recipients, fail_silently=True)
Summary of Adjustments:
- Added AJAX to handle the form submission asynchronously.
- Updated the
ContactView
to return JSON responses. - Display a success message on the same page after a successful form submission.
With these adjustments, the form will be submitted without redirecting or reloading the page, and a success message will be displayed on the same page.
Sending the email:
-
This line uses Django’s built-in
send_mail
function fromdjango.core.mail
to send the email. -
Parameters:
- subject: The subject of the email.
- message: The body of the email.
- sender: The email address that appears as the sender.
- recipients: The list of recipient email addresses.
- fail_silently=True: If set to True, errors will not raise exceptions and will fail silently.
How Does It Send Mail?
The send_mail
function from Django’s django.core.mail module is used to send the email. Here’s how it works:
-
Setup:
Django must be configured to send emails. This typically involves setting up email backend settings in your
settings.py
file. For example: -
Sending:
-
When the
send_mail
function is called: -
Django constructs an email message with the provided subject, message body, sender, and recipient list. It then sends the email using the configured email backend (e.g., SMTP server).
-
-
Handling Failures:
- By setting
fail_silently=True
, any issues during the sending process (e.g., network issues, incorrect email settings) will not raise an exception. This means the application will not crash due to email sending failures, though it’s often useful to handle such cases more gracefully in production environments.
- By setting