1

I have this template where I have a form for submitting an email address, and I'm trying to make a checkbox so that users can choose whether to receive email notifications or not.

{% extends "base_generic.html" %}

{% block content %}
<h1>{{ user.username }}</h1>

<p> Email comfirmed? {{ user.profile.email_confirmed }}</p>

{% if user.profile.email_confirmed %}
  <p>Email confimed as {{ user.email }}</p>
{% else %}
<form method="post">
    {% csrf_token %}
    {% for field in form %}
      <p>
        {{ field.label_tag }}<br>
        {{ field }}
        {% if field.help_text %}
          <small style="color: grey">{{ field.help_text }}</small>
        {% endif %}
        {% for error in field.errors %}
          <p style="color: red">{{ error }}</p>
        {% endfor %}
      </p>
    {% endfor %}
    <button type="submit">Authentificate</button>
  </form>
{% endif %}
{% if posts %}
<p>Your posts: </p>
<ul>
      <li> {{ posts.author }} {{ posts.pub_date }}
          {% if post.last_edited != null %}
            Last edited: {{ post.last_edited }}
          {% endif %}
              <br>  
      <a href="{% url 'fortykwords:detail' posts.id %}">{{ posts.title }}</a></li>
      {% for tag in posts.tags.all %}
          <a href="{% url 'fortykwords:tag' tag.name %}">{{ tag.name }}</a>
      {% endfor %}

{% endif %}
</ul>
{% else %}
  <p>No posts are available.</p>
{% endif %}

<input type="checkbox" name="checkbox" id="{{request.user.id}}">Send me an email notifications when I receive a message.<br>


    <script type="text/javascript">
    window.CSRF_TOKEN = "{{ csrf_token }}";
      $(document).ready(function(){
          $("input:checkbox").change(function() { 
              if($(this).is(":checked")) { 
                  $.ajax({
                      url: "/permissions/",
                      type: 'POST',
                      data: { strID:$(this).attr("id"), strState:"1" },
                      csrfmiddlewaretoken: jQuery("[name=csrfmiddlewaretoken]").val(),
                  }
                );
              } else {
                  $.ajax({
                      url: "/permissions/",
                      type: 'POST',
                      data: { strID:$(this).attr("id"), strState:"0" },
                      csrfmiddlewaretoken: jQuery("[name=csrfmiddlewaretoken]").val(),
                  });
              }
          }); 
      });
  </script>
{% endblock %}

The problem is that when I click the checkbox, it gives me the following error:

[02/Sep/2018 09:22:54] "POST /permissions/ HTTP/1.1" 403 2513
Forbidden (CSRF token missing or incorrect.): /permissions/

I know it's something related to the CSRF token, but I have tried many variations and I don't know what it could be. I suspect it's because I am using one token for the form and another for the AJAX request. What should I change so that the CSRF token is submitted successfully?

  • Maybe because your tag is not in form? – SampleText2k77 Sep 02 '18 at 09:51
  • Woops! But I changed it to `
    Send me an email notifications when I receive a message.
    ` but it didn't work.
    –  Sep 02 '18 at 10:01
  • Maybe this is related to your issue? https://stackoverflow.com/questions/5100539/django-csrf-check-failing-with-an-ajax-post-request – SampleText2k77 Sep 02 '18 at 10:05
  • 1
    I'm not sure why your Ajax is trying to get the token again from the input. You already have it, in `window.CSRF_TOKEN`; you should use that.. – Daniel Roseman Sep 02 '18 at 10:08
  • You need to add a header variable to your ajax request called: `'X-CSRFToken'` so your headers will include `'X-CSRFToken': PUT_YOUR_CSRF_TOKEN_HERE` – Chiheb Nexus Sep 02 '18 at 11:23
  • @ChihebNexus It didn't work, at least the way I tried it. –  Sep 05 '18 at 16:29

1 Answers1

2

In AJAX docs, I don't see any setting option csrfmiddlewaretoken.

You need to pass the token in either data or set header X-CSRFToken.

Solution:

$.ajax({
  url: "/permissions/",
  type: 'POST',
  data: {
    strID: $(this).attr("id"),
    strState: "0",
    csrfmiddlewaretoken: jQuery("[name=csrfmiddlewaretoken]").val()
  },
  // or you can set the header
  // headers: {
  //   "X-CSRFToken": jQuery("[name=csrfmiddlewaretoken]").val()
  // }
})
Sachin
  • 3,576
  • 1
  • 15
  • 24