I am using Django 3.2
I am creating a simple newsletter subscription form. The form submission returns JSON to the frontend, which should then be used to update parts of the page - however, when I post the form, the JSON string is displayed as text on a new page.
Here is the route that calls the view:
urlpatterns = [
# ...
path('subscription', BlogsubscriberCreateView.as_view(), name='subscription-post'),
# ...
]
Here is my class based view:
class BlogsubscriberCreateView(CreateView):
model = BlogPostSubscriber
form_class = BlogSubscriptionForm
http_method_names = ['post']
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
content_type = "application/json"
if not form.is_valid():
return JsonResponse({'ok': 0, 'msg': form.errors.get('email')[0]}, content_type=content_type, status=200)
else:
email = form.cleaned_data.get("email")
subscriber = BlogPostSubscriber(email= email)
subscriber.save()
# send email to confirm opt-in
email_message='Please confirm your subscription'
message = f"A confirmation email has been sent to {email}. Please confirm within 7 days"
return JsonResponse({'ok': 1, 'msg': message}, content_type=content_type, status=200)
Here is a snippet of the HTML containing the form:
<div class="col-lg-8 content">
<form id="blog-subscription" action="{% url 'blog:subscription-post' %}" method="post">
{% csrf_token %}
<br />
<h3>Some title</h3>
<br />
<p>Lorem ipsum ...</p>
<br />
<h4 id='submit-response-h4'>SUBSCRIBE TO OUR BLOG</h4>
<div id="submit-response" class="input-group">
<span id="email-error"></span>
<input type="email" id="blog-subscription-email" name="email" class="form-control" placeholder="Enter your email" required="true">
<span class="input-group-btn">
<button id="subscribe-btn" class="btn" type="submit">Subscribe Now</button>
</span>
</div>
</form>
Here is the Javascript that is responsible for updating the page:
$().ready(function() {
$('form#blog-subscription button#subscribe-btn.btn').on('click', function(e){
let email = $('#blog-subscription-email').val().trim().toLowerCase();
if (email.length && isValidEmail(email)){
e.preventDefault();
$.post({
url: "{% url 'blog:subscription-post' %}",
dataType: 'json',
data: {
email: email,
csrfmiddlewaretoken: '{{ csrf_token }}'
},
success: function (data){
let ok = data.ok;
if (ok){
if ($('#submit-response-h4').length){
$('#submit-response-h4').remove();
}
$('#submit-response').text(data.msg);
}
else{
$('#email-error').text(data.msg);
}
}
});
}
});
});
I placed an alert note in my Javascript and realised that it is simply not being called at all. I don't understand what is going on - if the Javascript is not being called - how does JQuery know to call the post function to the correct URL? (form has no action attribute!).
Typical example of a response (with a bad email) shown at http://example.com/path/to/subscription:
{"ok": 0, "msg": "Please use a different email service provider"}
What is causing this problem - and how do I fix it?