Django CSRF missing or incorrect Ajax POST without jquery (Vanilla JavaScript)

Viewed 102

when i got this error when i was using jquery i simple do:

data: {'csrfmiddlewaretoken': "{{csrf_token}}"}

Now I'm trying to move to vanilla JavaScript, here is my ajax call

<script>
    document.addEventListener('DOMContentLoaded', function () {
        document.querySelector('#sendMessage').onclick = function (e) {
            e.preventDefault();
            let xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function (e) {
                if (this.readyState == 4 && this.status == 200) {
                    alert('success')
                    let response = this.responseText
                    console.log(response)
                } else {
                    console.log(this.status)
                    console.log(this.readyState)
                }
            };
            xhr.open("POST", "{% url 'chat:room' room.id %}", true);
            // Send data csrf_token, content, area
            xhr.setRequestHeader('Content-type', 'application/json');
            data = {
                'csrfmiddlewaretoken': '{{ csrf_token }}',
                'content': document.querySelector('#id_content').value,
                'area': parseInt(document.querySelector('#id_area').value),
            }
            console.log(data)
            xhr.send(JSON.stringify(data));
        }
    });
</script>

However i get this error:

Forbidden (CSRF token missing or incorrect.): /chat/room/3/
[04/Oct/2020 05:25:16] "POST /chat/room/3/ HTTP/1.1" 403 2513

I have been searching for a while but all answers are solving it for jquery not vanilla js, Any help?

Update

Views.py:

def room(request, room_id):
    room = get_object_or_404(Room, pk=room_id)
    if request.method == 'GET':
        return render(request, 'chat/room.html', {'room': room})
    else:
        print(request.POST)
        message = Message.objects.create(
            user=request.user, content=request.POST.get('content'), room=room)
        message.save()
    return JsonResponse({})
1 Answers

set additional request header for CSRF:

# code

xhr.setRequestHeader('X-CSRFToken', '{{ csrf_token }}');

#code
Related