send views.py request.POST with JavaScript

Hey,
I know there are like hundreds of questions of this at stackoverflow, but I think I misunderstand something.

I’m trying to send a request to my views.py with JavaScript and catch it in vviews.py with request.POST, but it doesn’t catch anything.

Can somebody tell me, what I’m doing wrong in this code?

views.py

def my_account(request, *args, **kwargs):
    if request.POST:
        return HttpResponse("POST request")

    return render(request, "account/my-account.html")

my JavaScript:

deleteAccountBtn.addEventListener("click", () => {

    let formData = new FormData()
    formData.append("delete", "account")

    fetch('', { // it should send to this site, like a <form method="post" acction=""> does
        method: 'POST',
        headers: {
            "X-CSRFToken": getCookie("csrftoken")
        },
        body: formData
    })
})

function getCookie(name) {
    const value = `; ${document.cookie}`;
    const parts = value.split(`; ${name}=`);
    if (parts.length === 2) return parts.pop().split(';').shift();
}

Hi DevNick, thank you for sharing the various bits of code. That’s good to have. The piece of information we do need is what are you expecting to happen and what is actually happening? I suspect you’re encountering a 403 response and it’s related to the CSRF validation, but I don’t want to make that assumption. If you have any error messages, please share that in full. If you have inspected what the request looks like going to the server (check browser dev tools > network panel), that information is also great to have.

Hi CodenameTim, thanks for your answer.

I don’t get any errors in my console.
I send the csrftoken in my fetch request, so I don’t get a 403 error.

headers: {
            "X-CSRFToken": getCookie("csrftoken")
        },

When I log my function getCookie(“csrftoken”) I get this value back eBY9xuDhiOBNneSgNHpdFyu51g9Y0ng4 .
And that’s the same value that my cookie has (see image below).

So I don’t think it’s a csrftoken error.

Here’s the request in the network panel:

Gotcha, I didn’t mean to imply it was a CSRF problem, but that I assumed it was without more information.

Can you describe your problem? You description should include what you expect to happen and what is actually happening.

I am trying to manage multiple post requests in views.py:

1. function (works):
On the my-account page, I want you to be able to change your customer data (e.g. name, last name, gender). This function runs on a HTML form …. If I submit this HTML form, I can catch the request in the views.py with if request.POST: and execute a function (in this case, to save the changed customer data from the form to the database).

2nd Function (does not work):
You should be able to delete your account. If one clicks on the button “delete”, a message with the content “delete” should be sent to the views.py.
When I receive a request with the content “delete” in views.py, another function should be executed to delete the account.
The problem is that I can’t catch the request in views.py with if request.POST:.

Additionally, there should be other functions, but the principle remains the same.

I would like to avoid creating an additional page for each function, like it is done in the YouTube videos or docs.

E.g. for the function “Change password”. The current procedure on my website is as follows:

  1. you click on “change password”.
  2. you will be redirected to a page to change your password
  3. if you have changed your password successfully you will be redirected to a success page

I would like to omit these two intermediate steps so that the process is as follows:

  1. you click on “change password”.
  2. a HTML opens to change the password
  3. you get a success message with messages.success()

I would add a couple of print statements at the beginning of the my_account function to see exactly what is being submitted to that view.
I’d start with:

print(request)
print(request.body)
print(request.POST)
print(request.META)

Maybe try replacing the request.POST with request.method == "POST"

def my_account(request, *args, **kwargs):
    if request.method == "POST":
        return HttpResponse("POST request")

    return render(request, "account/my-account.html")

I know request.POST will also work, but still you might give this a try

Okay after long testing I could fix the problem.

Reference: python - Django - taking values from POST request, JavaScript fetch API - Stack Overflow

Here’s the solution:

JavaScript (has to be in the HTML file):

<script>
    data = JSON.stringify({
        headline: "Testing",
        tag: "Testing",
        background_image: "Testing",
        content: "Testing",
        user: 1
    })

    let csrftoken = getCookie('csrftoken');
    let response = fetch("", {
        method: 'POST',
        body: data,
        headers: {
            'Accept': 'application/json, text/plain, */*',
            'Content-Type': 'application/json',
            "X-CSRFToken": csrftoken
        },
    })


    function getCookie(name) {
        let cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            let cookies = document.cookie.split(';');
            for (let i = 0; i < cookies.length; i++) {
                let cookie = cookies[i].trim();
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
</script>

And in views.py:

def test(request):
    if request.method == "POST":
        import json

        post_data = json.loads(request.body.decode("utf-8"))

        print(post_data)

    return render(request, "test/test.html")

I don’t understand how it’s working, but it works.