CSRF verification failed. Request aborted - python

I try to build a very simple website where one can add data into sqlite3 database. I have a POST form with two text input.
index.html:
{% if top_list %}
<ul>
<b><pre>Name Total steps</pre></b>
{% for t in top_list %}
<pre>{{t.name}} {{t.total_steps}}</pre>
{% endfor %}
</ul>
{% else %}
<p>No data available.</p>
{% endif %}
<br>
<form action="/steps_count/" method="post">
{% csrf_token %}
Name: <input type="text" name="Name" /><br />
Steps: <input type="text" name="Steps" /><br />
<input type="submit" value="Add" />
</form>
forms.py:
from django import forms
from steps_count.models import Top_List
class Top_List_Form(forms.ModelForm):
class Meta:
model=Top_List
views.py:
# Create your views here.
from django.template import Context, loader
from django.http import HttpResponse
from steps_count.models import Top_List
from steps_count.forms import Top_List_Form
from django.template import RequestContext
from django.shortcuts import get_object_or_404, render_to_response
def index(request):
if request.method == 'POST':
#form = Top_List_Form(request.POST)
print "Do something"
else:
top_list = Top_List.objects.all().order_by('total_steps').reverse()
t = loader.get_template('steps_count/index.html')
c = Context({'top_list': top_list,})
#output = ''.join([(t.name+'\t'+str(t.total_steps)+'\n') for t in top_list])
return HttpResponse(t.render(c))
However, when I click the "submit" button, I get the 403 error:
CSRF verification failed. Request aborted.
I have included {% csrf_token %} in index.html. However, if it is a RequestContext problem, I really have NO idea on where and how to use it. I want everything to happen on the same page (index.html).

You may have missed adding the following to your form:
{% csrf_token %}

Use the render shortcut which adds RequestContext automatically.
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render
from steps_count.models import Top_List
from steps_count.forms import Top_List_Form
def index(request):
if request.method == 'POST':
#form = Top_List_Form(request.POST)
return HttpResponse("Do something") # methods must return HttpResponse
else:
top_list = Top_List.objects.all().order_by('total_steps').reverse()
#output = ''.join([(t.name+'\t'+str(t.total_steps)+'\n') for t in top_list])
return render(request,'steps_count/index.html',{'top_list': top_list})

When you found this type of message , it means CSRF token missing or incorrect. So you have two choices.
For POST forms, you need to ensure:
Your browser is accepting cookies.
In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
The other simple way is just commented one line (NOT RECOMMENDED)('django.middleware.csrf.CsrfViewMiddleware') in MIDDLEWARE_CLASSES from setting tab.
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

add it to the setting file
CSRF_TRUSTED_ORIGINS = [
'https://appname.herokuapp.com'
]

One more nicest alternative way to fix this is to use '#csrf_exempt' annotation.
With Django 3.1.1 you could just use #csrf_exempt on your method.
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def index(request):
and you don't need to specify {% csrf_token %} in your html.
happy learning..

A common mistake here is using render_to_response (this is commonly used in older tutorials), which doesn't automatically include RequestContext. Render does automatically include it.
Learned this when creating a new app while following a tutorial and CSRF wasn't working for pages in the new app.

In your HTML header, add
<meta name="csrf_token" content="{{ csrf_token }}">
Then in your JS/angular config:
app.config(function($httpProvider){
$httpProvider.defaults.headers.post['X-CSRFToken'] = $('meta[name=csrf_token]').attr('content');
}

if you are using DRF you will need to add #api_view(['POST'])

function yourFunctionName(data_1,data_2){
context = {}
context['id'] = data_1
context['Valid'] = data_2
$.ajax({
beforeSend:function(xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
if (settings.url == "your-url")
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
},
url: "your-url",
type: "POST",
data: JSON.stringify(context),
dataType: 'json',
contentType: 'application/json'
}).done(function( data ) {
});

If you put {%csrf_token%} and still you have the same issue, please try to change your angular version. This worked for me. Initially I faced this issue while using angular 1.4.x version. After I degraded it into angular 1.2.8, my problem was fixed. Don't forget to add angular-cookies.js and put this on your js file.
If you using post request.
app.run(function($http, $cookies) {
console.log($cookies.csrftoken);
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
});

USE decorator:
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def method_name():
# body

Ensure that your browser is accepting cookies. I faced the same issues.

1) {% csrf_token %} is not in template
-- or --
2) {% csrf_token %} is outside of html-form

Related

Django CreateView not updating context data

I have a form in a bootstrap modal, and I want to keep that modal open after submission. I am using CreateView and trying to pass an additional variable to the template in front-end where I could check if the flag is set or not, but the flag is always False even after submission. Here is what I have:
url.py
from django.urls import path
from .views import MescData
urlpatterns = [
path('mesc', MescData.as_view(), name='mesc')
]
views.py
from django.urls import reverse
from django.views.generic.edit import CreateView
from .forms import MescForm
from .models import Mesc
class MescData(CreateView):
model = Mesc
form_class = MescForm
template_name = 'Materials/mesc_data.html'
successful_submit = False # Flag to keep the add entry modal open
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['successful_submit'] = self.successful_submit
return context
def get_success_url(self):
return reverse('mesc')
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
self.successful_submit = True
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form, **kwargs):
# self.successful_submit = True
return super(MescData, self).form_valid(form, **kwargs)
And in Template, I'm checking it like this:
{% if successful_submit %}
<h1>Flag is set</h1>
{% endif %}
Is there a way to pass non-form-related data in CreateView to the template without having to change the url.py (i.e. adding variable data to url path)?
EDIT:
I tried printing the self.successful_submit in form_valid() and post() methods and it is indeed being updated to True, but in the template it is still being passed on as False.
This is the core problem: "I have a form in a bootstrap modal, and I want to keep that modal open after submission."
Simple answer: Use Ajax.
We do now have HTML over the wire as a paradigm gaining popularity, but I'm not familiar enough with it to discuss it. So I will use Ajax to show a solution. This particular solution uses a general ajax template, and the result of a post is a rendered Django template that you can use to just replace the HTML in your already rendered page.
Also, few people like JavaScript, but that is not a good enough reason to avoid using it. It is basically mandatory in any web application you're running. Even HTML over the wire uses a minimal amount of JavaScript to accomplish its goals.
First, write your Ajax view. I'm using django-rest-framework classes for this, and I'm providing an example for filling out a Calibration record. You can use whatever form you want; this is just my recipe for handling modals that you want keep open. In this view, I return a JSON response if the POST was successful. Otherwise, I return a rendered Django template.
from rest_framework.generics import (CreateAPIView, RetrieveAPIView,
UpdateAPIView, get_object_or_404)
from rest_framework.renderers import JSONRenderer, TemplateHTMLRenderer
from rest_framework.response import Response
class CalibrationCreateAjaxView(CreateAPIView, UpdateAPIView, RetrieveAPIView):
renderer_classes = (TemplateHTMLRenderer,)
template_name = "documents/form/cal.html"
def post(self, request, *args, **kwargs):
context = self.get_context(request)
calibration_form = context['calibration_form']
if calibration_form.is_valid():
calibration_form.save()
request.accepted_renderer = JSONRenderer()
return Response(status=201)
return Response(context, status=400)
def get(self, request, *args, **kwargs):
return Response(self.get_context(request))
#staticmethod
def get_context(request):
pk = request.GET.get("pk")
calibration_entry = get_object_or_404(CalibrationEntry, pk=pk) if pk else None
return {
'calibration_form': CalibrationFormAjax(request.POST or None, instance=calibration_entry)
}
I have my view template as well. It takes advantage of request.is_ajax, which is being deprecated. You'll need to add some middleware to keep using it. Here's my middleware. Add it to your settings file as well.
class IsAjaxMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
"""
request.is_ajax is being removed in Django 4
Since we depend on this in our templates, we are adding this attribute to request
Please review:
https://docs.djangoproject.com/en/4.0/releases/3.1/#id2
"""
def __call__(self, request):
request.is_ajax = request.headers.get('x-requested-with') == 'XMLHttpRequest'
return self.get_response(request)
general/ajax_modal.html
<!-- {% block modal_id %}{% endblock %}{% block modal_title %}{% endblock %} -->
{% block modal_body %}
{% endblock modal_body %}
general/modal.html
<div class="modal fade" id="{% block modal_id %}{{ modal_id }}{% endblock modal_id %}" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">×</span>
<span class="sr-only">Close</span>
</button>
<h4 class="modal-title">
{% block modal_title %}{{ modal_title }}{% endblock modal_title %}
</h4>
</div>
<div class="modal-body">
{% block modal_body %}
{% endblock modal_body %}
</div>
</div>
</div>
</div>
Even though, we're using Crispy Forms, you can get away without using it. I also have a general templatetag library that renders any errors on a form. You can write your own.
documents/form/cal.html
{% extends request.is_ajax|yesno:'general\ajax_modal.html,general\modal.html' %}
{% load crispy_forms_tags general %}
{% block modal_id %}new-cal-modal{% endblock modal_id %}
{% block modal_title %}Enter Calibration Information{% endblock modal_title %}
{% block modal_body %}
<div id="new-cal-form-container">
<form action="{% url 'calibration-create' %}" method="post" id="new-cal-modal-form" autocomplete="off" novalidate>
{% if request.is_ajax %}
{% crispy calibration_form %}
{% form_errors calibration_form %}
{% endif %}
<button type="submit" name="Submit" value="Save" class="btn btn-success button" id="submit">save</button>
</form>
</div>
{% endblock modal_body %}
So now that the Ajax view is all set up, I go back to the main page that will render the modal dialog when the user clicks a button. I have a block called "extraContent" in which I include the template of the modal form.
{% block extraContent %}
{% include 'documents/form/cal.html' %}
{% endblock extraContent %}
And now, the JavaScript, which requires jQuery, that I've added to the template. I guess I made my own jQuery plugin on top of that...
$.fn.modalFormContainer = function(optionsObject) {
//call it on the modal div (the div that contains a modal-dialog, which contains modal-header, modal-body, etc
// we expect there to be a form within that div, and that form should have an action url
// when buttons that trigger the modal are clicked, the form is fetched from that action url and replaced.
// optionsObject has formAfterLoadFunction and ajaxDoneFunction
var options = $.extend({}, $.fn.modalFormContainer.defaults, optionsObject);
var $modalFormContainer = $(this);
// get the buttons that trigger this modal to open
// add a click event so that the form is fetched whenever the buttons are clicked
// if data-pk is an attribute on the button, apply that to the querystring of the
// ajaxURL when fetching the form
var modalID = $modalFormContainer.prop("id");
var modalFormButtonSelector = "[data-target=#" + modalID + "][data-toggle=modal]";
function handleModalButtonClick(event) {
//does the button have an associated pk? if so add the pk to the querystring of the ajax url
// this is wrapped in a form so that it gets replaced by the ajax response.
var $button = $(this);
if (!$button.hasClass("disabled") && !$button.prop("disabled")) { //only do it if the button is "enabled"
var $placeholder = $("<form><h1>loading...</h1></form>");
var $modalForm = $modalFormContainer.find("form");
var ajaxURL = $modalForm.prop("action");
$modalForm.replaceWith($placeholder);
var pk = $button.data().pk;
if (pk) {
if (ajaxURL.indexOf("?") > 0) {
ajaxURL += "&pk=" + pk;
} else {
ajaxURL += "?pk=" + pk;
}
}
//fetch the form and replace $modalFormContainer's contents with it
$.ajax({
type: "GET",
url: ajaxURL
}).done(function(response) {
// re-create the form from the response
$modalFormContainer.find(".modal-body").html(response);
$modalForm = $modalFormContainer.find("form"); //we would still need to find the form
options.formAfterLoadFunction($modalForm);
});
} else {
return false; //don't trigger the modal.
}
}
//using delegation here so that dynamically added buttons will still have the behavior.
// maybe use something more specific than '.main-panel' to help with performance?
$(".main-panel").on("click", modalFormButtonSelector, handleModalButtonClick);
$modalFormContainer.on("submit", "form", function(event) {
// Stop the browser from submitting the form
event.preventDefault();
var $modalForm = $(event.target);
var ajaxURL = $modalForm.prop("action");
$modalForm.find("[type=submit]").addClass("disabled").prop("disabled", true);
var formData = $modalForm.serialize();
var internal_options = {
url: ajaxURL,
type: "POST",
data: formData
};
// file upload forms have and enctype attribute
// we should not process files to be converted into strings
if ($modalForm.attr("enctype") === "multipart/form-data") {
internal_options.processData = false;
internal_options.contentType = false;
internal_options.cache = false;
formData = new FormData($modalForm.get(0));
internal_options.data = formData;
}
$.ajax(internal_options).done(function(response) {
// blank out the form
$modalForm.find("input:visible, select:visible, textarea:visible").val("");
// remove errors on the form
$modalForm.find(".has-error").removeClass("has-error");
$modalForm.find("[id^=error]").remove();
$modalForm.find(".alert.alert-block.alert-danger").remove();
// hide the modal
$(".modal-header .close").click();
options.ajaxDoneFunction(response);
}).fail(function(data) {
// re-create the form from the response
$modalFormContainer.find(".modal-body").html(data.responseText);
options.formAfterLoadFunction($modalForm);
});
});
return this;
};
$.fn.modalFormContainer.defaults = {
formAfterLoadFunction: function($form) { return; },
ajaxDoneFunction: function(response) { return; }
};
$("#new-cal-modal").modalFormContainer({
formAfterLoadFunction: function($modalForm) {
$(".datetimeinput").datepicker('destroy');
$(".datetimeinput").datepicker();
},
ajaxDoneFunction: function(event) {
location.reload();
}
});
So upon reviewing this, I've realized that this recipe is far more complicated than I have tricked myself into believing. I sincerely apologize for that. I hope that you can review the code and get an idea of what is happening. There are some edge cases, such as dealing with dates and file uploads, that this recipe handles right now, but you may not actually need them. I should mention that the application that this came from is using Bootstrap 3, so its styling is not updated to the current Bootstrap 5 as of this writing. I should add that the main content of the app has a class of "main-panel" as used in this not-so-generic jQuery plugin.
I'm worried that I've gone and overwhelmed you into maintaining your position of trying to keep using a standard POST request. I guess you could just re-render the template with your POST since it'll be standard practice in your project. You could still get away without using a query string that way.

TypeError at /email-signup Object of type 'WSGIRequest' is not JSON serializable

Currently trying to make an email newsletter work with django 2.2 and MailChimp.
Got the code from a youtube video, I thought I unterstood it, but then I faced the error in the title.
I have tried various things such as just passing data=data in the subscribe function, but nothing I tried worked. The thing that concerns me is that it worked just fine in the video, and since it's not old I don't think that django has changed significantly.
Any help/explanation would be greatly appreciated.
views.py (not all imports)
from django.conf import settings
from .forms import EmailSignupForm
from django.http import HttpResponseRedirect
import json
import requests
MAILCHIMP_API_KEY = settings.MAILCHIMP_API_KEY
MAILCHIMP_DATA_CENTER = settings.MAILCHIMP_DATA_CENTER
MAILCHIMP_EMAIL_LIST_ID = settings.MAILCHIMP_EMAIL_LIST_ID
api_url = 'https://{dc}.api.mailchimp.com/3.0'.format(dc=MAILCHIMP_DATA_CENTER)
members_endpoint = '{api_url}/lists/{list_id}/members'.format(
api_url=api_url,
list_id=MAILCHIMP_EMAIL_LIST_ID
)
def subscribe(email):
data = {
"email_address": email,
"status": "subscribed",
}
print(data)
print(data[])
r = requests.post(
members_endpoint,
auth=("", MAILCHIMP_API_KEY),
data=json.dumps(data), # I think the error is caused here
)
return r.status_code, r.json()
def email_list_signup(request):
form = EmailSignupForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
email_signup_qs = Signup.objects.filter(email=form.instance.email)
if email_signup_qs.exists():
messages.info(request, "You are already subscribed")
else:
subscribe(form.instance.email)
messages.success(request, "You have subscribed successfully!")
form.save()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
class HomeView(ListView):
template_name = "home.html"
model = Post
form_class=EmailSignupForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
form = EmailSignupForm()
context['form'] = form
return context
def get_queryset(self):
return Post.objects.all().order_by('-published_date')[:5]
urls.py
from . import views
from django.conf.urls import url
urlpatterns = [
url(r'^email-signup$', views.subscribe,name="email-signup"),
]
forms.py
class EmailSignupForm(forms.ModelForm):
email = forms.EmailField(widget=forms.TextInput(attrs={
"type": "email",
"name": "email",
"id": "email",
"placeholder": "Type your email address",
}), label="")
class Meta:
model = Signup
fields = ('email', )
the form in home.html
{% block emailsignup %}
<div class="enter_email sidebar_element">
<p class="white">Get all new posts E-Mailed to you! No Ads, we promise.</p>
<form class="form " method='GET' action="{% url 'blog:email-signup' %}">
{% csrf_token %}
<!-- <input class="form-control " type="text" placeholder="Your email" name="email"> -->
{{ form }}
<button method="POST" class="btn btn-primary w-100 my-3" type="submit">Enter</button>
</form>
</div>
{% endblock %}
if any code is missing please let me know,
Thank you very much for your help.
I solved it.
The main thing was changing the form in the HTML itsself. After tracing the function calls as suggested, I was able to figure out that the subscribe function was not even called. I investigated and found out that my form had the "GET" instead of "POST" method. The url in the action attribute was right, but the button also had the method post, which I removed (dont know if that was necesarry, though).
Then I changed the url in urls.py into a path, which shouldnt make a difference, but is good practise in the newer django versions, I guess.
I also added an enctype="multipart/form-data" to the form, which, according to my tests, is not necessary.
So the final files will be:
form in home.html:
{% block emailsignup %}
<div class="enter_email sidebar_element">
<p class="white">Get all new posts E-Mailed to you! No Ads, we promise.</p>
<form class="form " method='POST' action="{% url 'blog:email-signup' %}" >
{% csrf_token %}
<!-- <input class="form-control " type="text" placeholder="Your email" name="email"> -->
{{ form }}
<button class="btn btn-primary w-100 my-3" type="submit">Enter</button>
</form>
</div>
{% endblock %}
urls.py:
from . import views
from django.conf.urls import url
from django.urls import path
urlpatterns = [
path('email-signup/', views.email_list_signup, name='email-signup'),
]
views.py:
from django.conf import settings
from .forms import EmailSignupForm
from django.http import HttpResponseRedirect
import json
import requests
MAILCHIMP_API_KEY = settings.MAILCHIMP_API_KEY
MAILCHIMP_DATA_CENTER = settings.MAILCHIMP_DATA_CENTER
MAILCHIMP_EMAIL_LIST_ID = settings.MAILCHIMP_EMAIL_LIST_ID
api_url = 'https://{dc}.api.mailchimp.com/3.0'.format(dc=MAILCHIMP_DATA_CENTER)
members_endpoint = '{api_url}/lists/{list_id}/members'.format(
api_url=api_url,
list_id=MAILCHIMP_EMAIL_LIST_ID
)
def subscribe(email):
data = {
"email_address": email,
"status": "subscribed"
}
r = requests.post(
members_endpoint,
auth=("", MAILCHIMP_API_KEY),
data=json.dumps(data)
)
return r.status_code, r.json()
def email_list_signup(request):
form = EmailSignupForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
email_signup_qs = Signup.objects.filter(email=form.instance.email)
if email_signup_qs.exists():
messages.info(request, "You are already subscribed")
print("in email_list_signup already subscribed.")
else:
subscribe(form.instance.email)
messages.info(request, "You have been successfully subscribed.")
print("in email_list_signup you have been subscribed")
form.save()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
The other files not mentioned again stay the same.
Thanks for helping guys

Why am i getting a csrf error in my POST form? (django/python) [duplicate]

This question already has answers here:
Django - CSRF verification failed
(3 answers)
Closed 8 years ago.
views.py
from django.shortcuts import render_to_response
from django.core.context_processors import csrf
def home(request):
c = {}
c.update(csrf(request))
if request.method == "POST":
username = request.POST.get("username", '')
password = request.POST.get("password", '')
return render_to_response("login_home.html", {"username":username, "password":password})
else:
return render_to_response("login_home.html")
login_home.html
{% extends "base.html" %}
{% block page %}
{{ name }}
<form action = "/blog/home/" method = "POST">{% csrf_token %}
<input type = "text" name = "username" placeholder = "username">
<input type = "text" name = "password" placeholder = "password">
<input type = "submit">
</form>
{{ username }}
{{ password }}
{% endblock %}
urls.py
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^home/$', 'blog.views.home'),
)
^^Here are my files. The problem is the error i get once i submit the form:
Forbidden (403)
CSRF verification failed. Request aborted.
I am not exactly sure what i am forgetting or missing. I am guessing its somewhere in the views function. Can someone point put the bit i am missing?
Thanks for any help.
You need to either use a RequestContext or return the context you have created with c.update(csrf(request)):
https://docs.djangoproject.com/en/dev/ref/contrib/csrf/
Use RequestContext, which always uses 'django.core.context_processors.csrf' (no matter what your TEMPLATE_CONTEXT_PROCESSORS setting). If you are using generic views or contrib apps, you are covered already, since these apps use RequestContext throughout.
Manually import and use the processor to generate the CSRF token and add it to the template context. e.g....
return render_to_response("login_home.html",
{"username":username, "password":password}
context_instance=RequestContext(request))

CSRF verification failed. Request aborted. // Dajaxice, Ajax

I am using Daxice library to create AJAX calls in my Django app.
When I create a POST method on a form I get the mentioned error:
Forbidden (403)
CSRF verification failed. Request aborted.
My settings.py have:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
'django.core.context_processors.request',
'django.contrib.messages.context_processors.messages',
'django.core.context_processors.csrf',
)
My urls.py
from django.conf.urls import patterns, include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from dajaxice.core import dajaxice_autodiscover, dajaxice_config
dajaxice_autodiscover()
urlpatterns = patterns('',
url(dajaxice_config.dajaxice_url, include('dajaxice.urls')),
url(r'^$', 'apps.views.home'),
)
urlpatterns += staticfiles_urlpatterns()
My views.py:
from django.http import HttpResponse
from django.template import loader, Context
from django.core.context_processors import csrf
def home(request):
t = loader.get_template('index.html')
html = t.render(Context( ))
return HttpResponse(html)
My template index.html:
{% load dajaxice_templatetags %}
<html>
<head>
<title>My base template</title>
<script src="http://code.jquery.com/jquery-latest.min.js"
type="text/javascript"></script>
{% dajaxice_js_import %}
<script type="text/javascript">
function shout(data){
alert(data.message)
}
</script>
</head>
<body>
<form method="POST" action="">{% csrf_token %}
Page: <input type="text" name="page"><br>
From: <input type="text" name="from"> (From < To) <br>
To: <input type="text" name="to"> (returns results before that day)<br>
<input type="submit" onclick="Dajaxice.apps.hello(shout);" value="Submit">
</form>
<br>
<br>
<input type="button" onclick="Dajaxice.apps.hello(shout);" value="Get message from server!">
</body>
</html>
And my ajax.py:
import simplejson
from dajaxice.decorators import dajaxice_register
#dajaxice_register(method='GET')
#dajaxice_register(method='POST', name='other_post')
def hello(request):
return simplejson.dumps({'message':'Hello from Python!'})
If I click the button, the message gets alerted. When I submit the form I get this error. How can I fix it?
Finally I believe I have fixed all the possibilities for the CSRF display in the debug page:
In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure:
Your browser is accepting cookies.
The view function uses RequestContext for the template, instead of Context.
In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.
Alright I think I got it. In the line:
<form>
...
<input type="submit" onclick="Dajaxice.apps.hello(shout);" value="Submit"></form>
...
</form>
If the type is button it works. It should be something with the submit behavior of the server request. I'm not an expert to explain why is this happening, so if somebody can explain I would gladly give the vote.
According to docs you can send csrf-token on every ajax-post request if you run this script first:
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
// test that a given url is a same-origin URL
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
// Send the token to same-origin, relative URLs only.
// Send the token only if the method warrants CSRF protection
// Using the CSRFToken value acquired earlier
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
It is written in jquery. If you want vanilla js, visit docs
Dajaxice does CSRF handling for you, you don't need any custom jQuery beforeSend code.
But you need to grant Dajaxice access to your CSRF cookie. Therefore:
Make sure CSRF_COOKIE_HTTPONLY is set to False in your settings.py!

CSRF Token missing or incorrect

Beginner at Django here, I've been trying to fix this for a long time now.
I do have 'django.middleware.csrf.CsrfViewMiddleware' in my middleware classes and I do have the token in my post form.
Heres my code, what am I doing wrong?
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from chartsey.authentication.forms import RegistrationForm
from django.template import RequestContext
from django.core.context_processors import csrf
def register(request):
if request.method == 'POST':
c = RequestContext(request.POST, {})
form = RegistrationForm(c)
if form.is_valid():
new_user = form.save()
return HttpResponseRedirect("/")
else:
form = RegistrationForm()
return render_to_response("register.html", {'form': form, }, )
Here's my Template:
{% block content %}
<h1>Register</h1>
<form action="" method="POST"> {% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
{% endblock %}
Update: This answer is from 2011. CSRF is easy today.
These days you should be using the render shortcut function return render(request, 'template.html') which uses RequestContext automatically so the advice below is outdated by 8 years.
Use render https://docs.djangoproject.com/en/2.2/topics/http/shortcuts/
Add CSRF middleware https://docs.djangoproject.com/en/2.2/ref/csrf/
Use the {% csrf_token %} template tag
Confirm you see the CSRF token value being generated, AND submitted in your form request
Original Response
My guess is that you have the tag in the template but it's not rendering anything (or did you mean you confirmed in the actual HTML that a CSRF token is being generated?)
Either use RequestContext instead of a dictionary
render_to_response("foo.html", RequestContext(request, {}))
Or make sure you have django.core.context_processors.csrf in your CONTEXT_PROCESSORS setting.
https://docs.djangoproject.com/en/dev/ref/contrib/csrf/
Or add the token to your context manually
Just add this to your views
return render_to_response("register.html", {'form': form, }, context_instance = RequestContext(request))
It will work!!
Try using render instead of render_to_response:
from django.shortcuts import render
render(request, "foo.html", {})
Django - what is the difference between render(), render_to_response() and direct_to_template()?
As stated in the link above it was introduced in Django 1.3 and automatically uses RequestContext
for Django version 3.0 add the below annotation
#csrf_protect
def yourfunc(request):
return render(request, '../your.html', None)
And don't forget add the below tag in your field
<form action="add/" method="post">
{% csrf_token %}
...
</form>
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.
The addition of RequestContext is the key when using render_to_response as mentioned by #Yuji 'Tomita' Tomita and #Njogu Mbau. However, what initially threw me off when I was struggling with this problem was that I had to add RequestContext to both the function in views.py that initially loads the template and to the function in views.py that handles the submission from the template.
Also, just for reference, here are some other links that discuss this same problem
Django - CSRF token missing or incorrect
Django 403 CSRF token missing or incorrect
Django --CSRF token missing or incorrect
Django CSRF Cookie Not Set *
Also got this error randomly on some pages after I installed django-livereload-server. Uninstalling django-livereload-server did the trick.
I had this issue too, but honestly, I hit refresh on my browser a few minutes later without changing anything and it worked that time. I had this message in my command line as so it might provide a clue as to what was causing the issue:
Not Found: /css/reset/reset.css
[03/Jul/2020 20:52:13] "GET /css/reset/reset.css HTTP/......
DJANGO/AJAX WORKFLOW FULL METHOD IS HERE :)
const url = "{% url 'YOUR_URL_NAME' pk=12345 %}".replace(/12345/, id.toString());
$.ajax({
type: 'POST',
url: url,
data: {'id':id, "csrfmiddlewaretoken": '{{csrf_token}}'},
beforeSend: function() { $('#response').text('Please wait ...'); },
success: function (response) {
console.log(response)
},
error: function (response) {
console.log(response)
}
})
Hope It Will Work !!!
What worked for me was commenting out the below line from my settings.py
'django.middleware.csrf.CsrfViewMiddleware'

Categories