In my users page, i have in place editing with ajax. And when i click edit, it works fine. But when i submit the form, it don't do anything. When i checked, this is the error:
CSRF verification failed. Request aborted.
So, how do I place {% csrf_token %} in my javascript? Please advice.
Thank you.
edit.js:
function bookmark_edit() {
var item = $(this).parent();
var url = item.find(".title").attr("href");
item.load("/save/?ajax&url=" + escape(url), null, function () {
$("#save-form").submit(bookmark_save);
});
return false;
}
$(document).ready(function () {
$("ul.bookmarks .edit").click(bookmark_edit);
});
function bookmark_save() {
var item = $(this).parent();
var data = {
url: item.find("#id_url").val(),
title: item.find("#id_title").val(),
tags: item.find("#id_tags").val()
};
$.post("/save/?ajax", data, function (result) {
if (result != "failure") {
item.before($("li", result).get(0));
item.remove();
$("ul.bookmarks .edit").click(bookmark_edit);
}
else {
alert("Failed to validate bookmark before saving.");
}
})
return false;
}
save_form.html:
<form id = "save-form" method="post" action="/save/">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Save" />
</form>
user_page.html:
{% extends "base.html" %}
{% block external %}
<script type = "text/javascript" src="{% static "assets/js/bookmark_edit.js" %}"></script>
{% endblock %}
{% block title %} {{username}} {% endblock %}
{% block head %} Bookmarks for {{username}} {% endblock %}
{% block content %}
{% include "bookmark_list.html" %}
{% endblock %}
view.py:
#login_required(login_url='/login/')
def bookmark_save_page(request):
ajax = request.GET.has_key('ajax')
if request.method == 'POST':
form = BookmarkSaveForm(request.POST)
if form.is_valid():
bookmark = _bookmark_save(request, form)
if ajax:
variables = RequestContext(request, {
'bookmarks':[bookmark],
'show_edit':True,
'show_tags':True
})
return render_to_response('bookmark_list.html', variables)
else:
return HttpResponseRedirect('/user/%s/' % request.user.username
)
else:
if ajax:
return HttpResponseRedirect('failure')
elif request.GET.has_key('url'):
url = request.GET['url']
title = ''
tags = ''
try:
link = Link.objects.get(url=url)
bookmark = Bookmark.objects.get(
link=link,
user = request.user
)
title = bookmark.title
tags = ' '.join(
tag.name for tag in bookmark.tag_set.all()
)
except ObjectDoesNotExist:
pass
form = BookmarkSaveForm({
'url':url,
'title':title,
'tags':tags
})
else:
form = BookmarkSaveForm()
variables = RequestContext(request, {
'form': form
})
if ajax:
return render_to_response(
'bookmark_save_form.html',
variables
)
else:
return render_to_response('bookmark_save.html',variables)
You are not sending the server generated csrf_token for the POST to verify the validity of the data. Hence the error.
As a part of the data part of the request, you need to send the token
csrfmiddlewaretoken: '{{ csrf_token }}'
Something like this
var data = {
url: item.find("#id_url").val(),
title: item.find("#id_title").val(),
tags: item.find("#id_tags").val(),
csrfmiddlewaretoken: '{{ csrf_token }}'
};
Or you could simply do:
var data = $('form').serialize()
if you want to send the whole form as a dictionary
var csrftoken = Cookies.get('csrftoken');
xhr.setRequestHeader("X-CSRFToken", csrftoken);
enter link description here
This is what I use. Not sure if it's applicable in your situation though.
// sending a csrftoken with every ajax request
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
crossDomain: false, // obviates need for sameOrigin test
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
}
}
});
Related
I just started with ajax but can't seem to find the fix for this. I think it might have to do with the comment_id vs the blog_id. (followed this tutorial: https://www.youtube.com/watch?v=VoWw1Y5qqt8&list=PLKILtxhEt4-RT-GkrDkJDLuRPQfSK-6Yi&index=39&ab_channel=AbhishekVerma).
This is what my views.py looks like
def like_comment(request):
comment = get_object_or_404(Comment, id=request.POST.get("comment_id"))
blog = get_object_or_404(BlogPost, id=request.POST.get("blog_id"))
comments = Comment.objects.filter(post=blog, reply=None)
if request.user in comment.likers.all():
comment.likers.remove(request.user)
else:
comment.likers.add(request.user)
context = {
"comments": comments,
"blog_post": blog,
"body": markdown2.markdown(blog.body),
"comment_form": CommentForm(),
}
if request.is_ajax():
html = render_to_string('blog/like_section.html',
context, request=request)
return JsonResponse({'form': html})
This is a snippet of my HTML
{% if request.user.is_authenticated %}
<form action={% url 'like_comment' %} method="POST">
{% csrf_token %}
{% if user in comment.likers.all %}
<input type="hidden" name="blog_id" value=" {{ blog_post.id }}">
<button type="submit" id="like" name="comment_id" value="{{ comment.id }}">Like</button>
{% else %}
<input type="hidden" name="blog_id" value=" {{ blog_post.id }}">
<button type="submit" id="like" name="comment_id" value="{{ comment.id }}">Dislike</button>
{% endif %}
{% else %}
<div><small class="comment_time">Login to Like</small></div>
{% endif %}
</form>
</div>
<small class="comment_time">{{ comment.total_likes }}
Likes</small>
And this is the javascript:
$(document).ready(function (event) {
$(document).on('click', '#like', function (event) {
event.preventDefault();
var pk = $(this).attr('value');
$.ajax({
type: "POST",
url: '{% url "like_comment" %}',
data: { 'blog_id': pk, 'csrfmiddlewaretoken': '{{ csrf_token }}' },
dataType: 'json',
success: function (response) {
$('#like_section').html(response['form'])
console.log($('#like_section').html(response['form']));
},
error: function (rs, e) {
console.log(rs.responseText);
},
});
});
});
I'm getting the following error:
Picture
I would start to check if the request header contains HTTP_X_REQUESTED_WITH='XMLHttpRequest'. You can do that with the debug function of the browser (e.g. firefox). Maybe your JS library does not send this header.
see the Django documentation:
https://docs.djangoproject.com/en/1.11/ref/request-response/#django.http.HttpRequest.is_ajax
def is_ajax(self):
return self.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
HttpRequest.is_ajax():
Returns True if the request was made via an XMLHttpRequest, by checking the HTTP_X_REQUESTED_WITH header for the string 'XMLHttpRequest'. Most modern JavaScript libraries send this header. If you write your own XMLHttpRequest call (on the browser side), you’ll have to set this header manually if you want is_ajax() to work.
If a response varies on whether or not it’s requested via AJAX and you are using some form of caching like Django’s cache middleware, you should decorate the view with vary_on_headers('X-Requested-With') so that the responses are properly cached.
I am trying to post user geolocation to Django class based view. Apparently, javascript is not so friendly to me. How can I post user geolocation to UserProfileView class based view in django, ajax?
<body>
<div>
<div>
<strong>Current Position: </strong> {{ profile.user_location }}<br/>
</div>
<label for="locations-status">Enable Location?</label>
<input type="checkbox" id="locations-status">
<form id="location_form" method="POST" action="{% url 'rent_app:add-location' %}">
{% csrf_token %}
<button type="button" id="send-my-url-to-django-button">Send URL to Django View</button>
</form>
{% block js %}
<script>
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
}
}
});
if ("geolocation" in navigator) {
navigator.geolocation.getCurrentPosition(
function (position) {
console.log('Position has been set successfully');
console.log(position.coords);
dataToSend = {
"permission": $("input[name=locations-status]").is(':checked'),
"user_location": position,
};
});
}
$("#send-my-url-to-django-button").click(function() {
$.ajax({
type: "POST",
dataType: 'json',
url: "{% url 'rent_app:add-location' %}",
data: JSON.stringify(dataToSend),
success: function (msg) {
console.log('Succeeded!');
},
error: function (err) {
console.log('Error!');
}
});
}, function (error) {
console.log('Position could not be obtained.');
}
);
</script>
{% endblock %}
</body>
views.py:
class UserProfileView(View):
form_class = UserProfileModelForm
template_name = "user_profile.html"
def get(self, *args, **kwargs):
form = self.form_class()
user_locations = UserProfile.objects.user_location()
return render(self.request, self.template_name,
{"form": form, "user_location": user_locations})
def post(self, *args, **kwargs):
if self.request.is_ajax and self.request.method == "POST":
form = self.form_class(self.request.POST)
if form.is_valid():
instance = form.save()
ser_instance = serializers.serialize('json', [ instance, ])
# send to client side.
return JsonResponse({"instance": ser_instance}, status=200)
else:
return JsonResponse({"error": form.errors}, status=400)
return JsonResponse({"error": ""}, status=400)
The context is {"form": form, "user_location": user_locations}) you don't have any profile passed in the context. I think you need to use {{ user_location }} instead of {{ profile.user_location }}
Just make the javascript work. Thank you, that would be helpful.
I followed the instructions of this tutorial
https://simpleisbetterthancomplex.com/tutorial/2016/08/29/how-to-work-with-ajax-request-with-django.html
to check "User already exists or not" but Django still rejecting my POST request. I could use some help complying with Django's CSRF protection mechanism via my AJAX post. I've followed the directions here:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
But it didnt help me. It is my result in console:
{% extends 'base.html' %}
{% block title %}
Register
{% endblock %}
{% load crispy_forms_tags %}
{% block body %}
<div class="container">
<h1 class="text-center">Regiser</h1>
<form class="form-group" method="POST" data-validate-username-url = "{% url 'validate_username' %}">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" name="Register" class="btn btn-primary text-center" value="Register">
</form>
</div>
{% endblock %}
{% block script %}
<script>
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 = 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;
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$(document).ready(function() {
var csrftoken = getCookie('csrftoken');
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
});
$("#id_username").change(function() {
var form = $(this).closest("form");
$.ajax({
url: form.attr('data-validate-username-url'),
data: form.serialize(),
dataType: 'json',
success: data => {
if (data.is_taken) {
alert(data.error_message);
}
}
});
});
</script>
{% endblock %}
GET http://127.0.0.1:8000/ajax/validate_username?csrfmiddlewaretoken=kc6NtBw1pch0jjI0SGHhCVBeAKYWZrppOFgxHUaisCVqJUUlY73orIM3PDI0kejA&username=Tony&email=&password1=&password2= 500 (Internal Server Error)
send # jquery-3.5.0.min.js:2
ajax # jquery-3.5.0.min.js:2
(anonymous) # (index):79
dispatch # jquery-3.5.0.min.js:2
v.handle # jquery-3.5.0.min.js:2
FieldError at /ajax/validate_username
Cannot resolve keyword 'username_iexact' into field. Choices are: date_joined, email, first_name, groups, id, is_active, is_staff, is_superuser, last_login, last_name, logentry, orders, password, user_permissions, username
Request Method: GET
Request URL: http://127.0.0.1:8000/ajax/validate_username?csrfmiddlewaretoken=kc6NtBw1pch0jjI0SGHhCVBeAKYWZrppOFgxHUaisCVqJUUlY73orIM3PDI0kejA&username=Tony&email=&password1=&password2=
Django Version: 3.0.5
Exception Type: FieldError
Exception Value:
Cannot resolve keyword 'username_iexact' into field. Choices are: date_joined, email, first_name, groups, id, is_active, is_staff, is_superuser, last_login, last_name, logentry, orders, password, user_permissions, username
Exception Location: C:\Users\Le Dai Thang\Envs\myproject\lib\site-packages\django\db\models\sql\query.py in names_to_path, line 1483
Python Executable: C:\Users\Le Dai Thang\Envs\myproject\Scripts\python.exe
Python Version: 3.7.7
Python Path:
['C:\Users\Le Dai Thang\Lecture7\project3',
'C:\Users\Le Dai Thang\Envs\myproject\Scripts\python37.zip',
'c:\users\le dai thang\appdata\local\programs\python\python37\DLLs',
'c:\users\le dai thang\appdata\local\programs\python\python37\lib',
'c:\users\le dai thang\appdata\local\programs\python\python37',
'C:\Users\Le Dai Thang\Envs\myproject',
'C:\Users\Le Dai Thang\Envs\myproject\lib\site-packages']
HTML
{% if todo_array %}
<ul>
{% for TodoList in todo_array %}
<li class="listItems" name="listItem" id="item{{ forloop.counter }}" onClick = "myFunction({{ forloop.counter }})" >
{{ TodoList.todo_text }}
</li>
{% endfor %}
</ul>
{% else %}
<p> Add some Todo's !! </p>
{% endif %}
Javascript
var csrftoken = getCookie('csrftoken');
function myFunction(value){
console.log("clicked")
$.ajaxSetup({
headers: { "X-CSRFToken": getCookie("csrftoken") },
type:"POST",
{% load static %}
url:"{%url 'home'%}",
data: {
id : value
},
success: function(data) {
console.log('success',data);
},
});
}
Python
def home(request):
if request.method == 'POST':
todelete = request.POST.get('id')
print(todelete)
return render(request, 'home/mainList.html', context)
I'm trying to send the ID from html using javascript into python by making an ajax call. However the post data isn't working. How can I fix my code?
Edit.
Getting a server internal error 500 now.
Urls.py
urlpatterns = [
path('', views.home, name='home'),
path('logout', views.logout_attempt, name='logout')
]
I'm trying to implement a like functionality in my Django app using AJAX but, when I try to do that I'm getting an POST http://localhost:8000/forum/like/ 404 (Not Found). All I wanna do is to add/remove users from the likes list without refreshing the entire page.
views.py
#require_POST
def toggle_like(request):
if request.method == "POST":
user = request.user
slug = request.POST.get('slug', None)
question = get_object_or_404(Question, slug=slug)
if question.likes.filter(id=user.id).exists():
question.likes.remove(user)
else:
question.likes.add(user)
context = {'likes-count': question.likes.count}
return HttpResponse(json.dump(context), content_type='application/json')
urls.py
from django.urls import path
from . import views
app_name = 'forum'
urlpatterns = [
path('like/', views.toggle_like, name='toggle-like'),
]
question.html
{% block javascript %}
<script>
$('#like').click(() => {
$.ajax({
method: 'POST',
url: "{% url 'forum:toggle-like' %}",
data: {
'slug': $(this).attr('name'),
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
dataType: 'json',
success: (response) => {
alert(response.message);
},
error: (response, error) => {
alert(response.responseText);
}
})
})
</script>
{% endblock %}
{% block content %}
<p>Likes: {{ question.likes.count }} <input type="button" id="like" name="{{ question.slug }}" value="Like" /></p>
{% endblock %}