Getting a django.utils.datastructures.MultiValueDictKeyError using ajax

I am trying to use the ajax post function to post data from my contact form in one of my templates. However, I am getting a 'django.utils.datastructures.MultiValueDictKeyError' when I make the request.

The error is a server error and it is displayed as shown

django.utils.datastructures.MultiValueDictKeyError: 'name'

It is being triggered in the view.py folder on the line with the code

name = request.POST['name']

Here is my model for the message:

class Message(models.Model):
     name = models.CharField(max_length=255)
     email = models.CharField(max_length=255)
     content = models.TextField(max_length=10000)
     created_at = models.DateTimeField(auto_now_add=True)

This is my view.py:

def save_message(request):
     if request.method=='POST':
          name = request.POST['name']
          email = request.POST['email']
          content = request.POST['content']
          Message.objects.create(
               content = content,
               name = name,
               email = email
          )
          messages.success(request, f'Your message has been sent. Expect a response soon!')
          return JsonResponse({'bool':True})

This is the form in the index template

{% csrf_token %}
                     <form class="contactForm" id="contactForm">
                         <div class="form-floating">
                             <input class="form-control" class="message-name" id="name" type="text" placeholder="Enter your name..." />
                         </div>
                         <div class="form-floating">
                             <input class="form-control" class="message-email" id="email" type="email" placeholder="Enter your email..." />
                         </div>
                         <div class="form-floating">
                             <textarea class="form-control" id="message" class="message-text" placeholder="Enter your message here..."></textarea>
                         </div>
                         <br />
                         
                         <button class="btn btn-primary text-uppercase save-message" id="submitButton" type="submit">Send</button>
                     </form>

And this is my ajax:

{% block script %}
<script>
    $(document).ready(function(){
    

        // This is for the post messages for non-logged in users
        $(".save-message").on('click',function(){
            var _content=$(".message-text").val();
            var _messageName=$(".message-name").val();
            var _messageEmail=$(".message-email").val();
            // Ajax 
            $.ajax({
                url:"/save-message",
                type:"POST",
                data:{
                    content:_content,
                    name:_messageName,
                    email:_messageEmail,
                    csrfmiddlewaretoken:"{{csrf_token}}"
                },
                dataType:'json',
                beforeSend:function(){
                    $(".save-message").addClass('disabled').text('Saving...');
                },
                success:function(res){
                    if(res.bool==true){
                        $(".message-text").val('');
                    }
                    $(".save-message").removeClass('disabled').text('submit');
                }
            });     
        });

  });


</script>
{% endblock %}

Using request.POST[] is for data sent with regular HTML forms, but not when sending data using AJAX (even if it is sent via POST). To access that you need the raw, request.body, and to parse that you need json, which also means you need to import json:

import json

def save_message(request):
    
    if request.method=='POST':
        
        data = json.loads(request.body)
        
        name = data['name']
        email = data['email']
        content = data['content']
        
        Message.objects.create(
           content = content,
           name = name,
           email = email
        )

        messages.success(request, f'Your message has been sent. Expect a response soon!')

        return JsonResponse({'bool':True})

The error would have occurred with email = request.POST['email'] or content = request.POST['content'] because request.POST is empty, so the keys, name, email, content, or any other key would have raised the MultiValueDictKeyError:.

Source: Django Docs:

HttpRequest.body

The raw HTTP request body as a bytestring. This is useful for processing data in different ways than conventional HTML forms: binary images, XML payload etc. For processing conventional form data, use HttpRequest.POST.

Back to Top