skip to Main Content

I think the problem is in part due to the fact im not using the HTML template tag since, I’m creating a project using the JS generating the HTML from there. For addressing this in the HTML i added this script(before the js script I use):

<script> var csrfToken = '{{ csrf_token }}'; </script>

Im using the following script after the form code to send the information to my django project:

const apiSendDataUser = (event) => {
    event.preventDefault();
    
    const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
    const formData = new FormData (event.target);
    fetch('https://127.0.0.1:8000/myProject/post_user',{
        method: 'POST',
        body: formData,
        headers: {
            'X-CSRFToken': csrfToken
        }
    })
    .then(response => {
        if (response.ok) {
            return response.json();
        } else {
            throw new Error('Error: ' + response.status);
        }
    })
    .then(data => {
        // Handle the response data
        console.log(data);
    })
    .catch(error => {
        // Handle any errors
        console.error(error);
    });
};

And finally, the post_user function on the views.py is:

@require_POST 

def post_user(request):

    try:
        email = request.POST['email']
        if not User.objects.filter(email).exists() :

            username = request.POST['username']
            password = request.POST['password']
            
            User.objects.create_user(username=username, password=password, email=email)

        return JsonResponse(
            {
                "success":True,
                "message": "Usuario añadido."
            }
            )
    
    except Exception as e:
        return JsonResponse({
            "success": False,
            "message": e.args[0]
        }, status=404) 

I think is all, I dont know how to handle things with the CSRF token, I hope you might help me in this regard. Thanks.

On this problem, I’ve tried to go to django documentation but still dont understand why im having this problems.

2

Answers


  1. The CSRF token is included in the HTML of the Django-rendered webpage as a cookie. You’re trying to include it in your script using a Django template tag, but since the form is generated using JavaScript, this token is not included correctly.

    Here’s how you can retrieve the CSRF token from the cookie:

    function get_cookie(n) {
        if (!document.cookie || document.cookie !== '')
          return null;
        
        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 + '='))
           return decodeURIComponent(cookie.substring(name.length + 1));
         
       }
    }
    let csrfToken = getCookie('csrftoken');
    
    

    After you can use it in the fetch request.

    fetch('https://127.0.0.1:8000/myProject/post_user',{
        method: 'POST',
        body: formData,
        headers: {
            'X-CSRFToken': csrfToken
        }
    })
    
    

    Also, check if Django settings have CSRF_COOKIE_NAME equal to csrftoken.
    If it has another value, you need to replace it when calling the get_cookie function.

    If this still doesn’t work, make sure that your Django view is properly set up to handle CSRF. The Django @csrf_exempt decorator can be used to test it.

    Login or Signup to reply.
  2. Answer
    In order to use const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
    you have to have {% csrf_token %} somewhere in your HTML template.

    Why this works
    When Django sees this it will replace {% csrf_token %} with something like
    <input type="hidden" name="csrfmiddlewaretoken" value=".............................">,

    which your JavaScript can then get using the QuerySelector. Usually it is placed within the <form>:

    <form>
        {% csrf_token %}
        ...
    </form>
    

    But since you are using JavaScript to send the form, it can be placed anywhere in your HTML:

    <div>{% csrf_token %}</div>
    

    Why your code does not work
    When Django sees this: <script> var csrfToken = '{{ csrf_token }}'; </script> it will replace {{ csrf_token }} with a random value, the actual token, so it will look something like this:

    <script> var csrfToken = 'some_random_string_which_is_the_token'; </script>
    

    Note the difference. Here with {{ csrf_token }} your querySelector fails, since there is no hidden input generated with the name=csrfmiddlewaretoken, which is what happens with {% csrf_token %}

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search