Reputation: 315
When i try to submit my ajaxified form that's working with the DRF API i get in the browser console!
POST http://localhost:8000/api/texts/ 403 (Forbidden)
here is my html file :
<form id="text-form" method="POST" action="">
<input type="text" name="title" placeholder="Title" class="form-control mb-3 pb-2"
maxlength="200" required id="title">
<input type="date" name="deadline" placeholder="Deadline" autocomplete="off"
class="form-control mb-3" id="myflatpickr">
<textarea name="requirements" cols="40" rows="4"
placeholder="requirements"
class="form-control col mt-3" maxlength="200" required id="requirements"></textarea>
<textarea name="document" cols="40" rows="10"
placeholder="document"
id="editor" class="form-control" required></textarea>
<button type="submit">Submit</button>
</form>
here is my javascript file
$("#text-form").submit(function (event) {
event.preventDefault();
$textData = $("#text-form").serialize()
$.ajax({
url: "http://localhost:8000/api/texts/",
method: "POST",
data: $textData,
success: function() {
console.log($textData)
},
error: function() {
console.log("there is an error")
}
})
});
in serializers.py:
from django.contrib.auth import get_user_model
from django.contrib.auth.password_validation import validate_password
from rest_framework import serializers
from .models import *
class TextSerializer(serializers.ModelSerializer):
author = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
class Meta:
model = Text
fields = '__all__'
in my views.py file:
class ApiTextList(generics.ListCreateAPIView):
queryset = Text.objects.all()
serializer_class = TextSerializer
permission_classes = [
permissions.AllowAny
]
class ApiTextDetail(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
http_method_names = ['get', 'head']
queryset = Text.objects.all()
serializer_class = TextSerializer
permission_classes = [
permissions.AllowAny
]
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
in urls.py
from django.urls import path
from . import views
urlpatterns = [
path('api/texts/', views.ApiTextList.as_view()),
path('api/texts/<int:pk>/', views.ApiTextDetail.as_view()),
]
note: when i try to add a text from the interface that drf provides in "localhost:8000/api/texts" i add it normally
Upvotes: 1
Views: 3781
Reputation: 157
try this, for Forbidden 403 :
$.ajax({
url: "http://localhost:8000/api/texts/",
method: "POST",
data: $textData,
contentType: "application/json;charset=utf-8",
dataType: "json",
headers: {"X-CSRFToken": "{{ csrf_token }}"},
success: function() {
console.log($textData)
},
error: function() {
console.log("there is an error")
}
})
Upvotes: 0
Reputation: 1843
Now that you told us the content of the details field, it should be easier to fix your problem.
The Django documentation advises you to get the CSRF token from the cookies.
It even gives you the following function to do that:
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
And you can then easily adapt your own code by adding those two lines:
$("#text-form").submit(function (event) {
event.preventDefault();
const csrftoken = getCookie('csrftoken'); // HERE: get the token
$textData = $("#text-form").serialize()
$.ajax({
url: "http://localhost:8000/api/texts/",
method: "POST",
data: $textData,
headers:{"X-CSRFToken": csrftoken }, // HERE: add it to the request header
success: function() {
console.log($textData)
},
error: function() {
console.log("there is an error")
}
})
});
If that does not work, please check that you are correctly using Session Authentication.
And to answer your other interrogation, this is normal that your registration view works without the CSRF token: in the DRF, only the views where you need to be authenticated require it.
Upvotes: 5
Reputation: 73
You are getting Error 403, which means the server understood the request but refuses to authorize it. You need to add an authorization token while sending an ajax request.
You can authorize a token on your page using this.
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
Then, you have to add the token to your ajax request.
$.ajax({
url: "http://localhost:8000/api/texts/",
method: "POST",
data: $textData,
csrfmiddlewaretoken: window.CSRF_TOKEN,
success: function() {
console.log($textData)
},
error: function() {
console.log("there is an error")
}
})
Upvotes: 0