My View
class MusicianLikesView(DetailView):
model = Musician
template_name = "guitar_blog/blog_detail.html"
def post(self, request, **kwargs):
song = self.get_object()
user_id = request.user.id
user_username = request.user.username
if request.user.is_authenticated:
if "Like1" in request.POST and user_username not in song.music_1_users.keys():
song.music_1_votes += 1
song.music_1_users[user_username] = user_id
song.save()
return JsonResponse({"likes": song.music_1_votes})
elif "Unlike1" in request.POST and user_username in song.music_1_users.keys():
song.music_1_votes -= 1
song.music_1_users.pop(user_username)
song.save()
return JsonResponse({"likes": song.music_1_votes})
My Urls
path('ajax/', MusicianLikesView.as_view(), name="song_likes"),
My Template
<form method="post" class="voting-setup top_song">
{% csrf_token %} {% if user.get_username in musician.music_1_users %}
<button name="Unlike1" type="submit" class="like-button">
<i class="fa-solid fa-guitar icon"
><span class="like-text">Unlike</span></i
>
</button>
{% else %}
<button name="Like1" type="submit" class="like-button">
<i class="fa-solid fa-guitar icon"
><span class="like-text">Like</span></i
>
</button>
{% endif %}
</form>
<span class="after-like first_song_likes">Liked {{ musician.music_1_votes }}</span>
My Javascript File
$(document).on("submit", ".top_song", function (event) {
event.preventDefault();
$.ajax({
type: "POST",
url: "ajax/",
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
},
success: function (response) {
console.log(response);
},
error: function (re) {
console.log(re);
}
});
});
My Error in Console
POST http://127.0.0.1:8000/guitar_blog/20/ajax/ 404 (Not Found)
My Changes in View
def musician_likes_view(request, pk):
song = Musician.objects.get(pk=pk)
user_id = request.user.id
user_username = request.user.username
if request.user.is_authenticated:
if "Like1" in request.POST and user_username not in song.music_1_users.keys():
song.music_1_votes += 1
song.music_1_users[user_username] = user_id
song.save()
return HttpResponse(song.music_1_votes)
elif "Unlike1" in request.POST and user_username in song.music_1_users.keys():
song.music_1_votes -= 1
song.music_1_users.pop(user_username)
song.save()
return HttpResponse(song.music_1_votes)
My Changes in URLS
path('ajax/', musician_likes_view, name="song_likes"),
My Error This is the error I got in my console
POST http://127.0.0.1:8000/guitar_blog/20/ajax/ 404 (Not Found)
My success function in my JavaScript file is not able to access my JsonResponse or HttpResponse, it is going to the Error Function . I have no data to pass in the form except "csrf_token" as it is just for a button click. I have accessed the second class of the form that is (".top_song") in the javascript file for submission. What am I doing wrong here?
New Changes
URL
path('guitar_blog/<int:pk>/ajax/', MusicianLikesView.as_view(), name="song_likes"),
View
if request.user.is_authenticated:
if "Like1" == request.POST["name"] and user_username not in song.music_1_users.keys():
song.music_1_votes += 1
song.music_1_users[user_username] = user_id
song.save()
return JsonResponse({"likes": song.music_1_votes})
elif "Unlike1" == request.POST["name"] and user_username in song.music_1_users.keys():
song.music_1_votes -= 1
song.music_1_users.pop(user_username)
song.save()
return JsonResponse({"likes": song.music_1_votes})
Javascript File
$(".top_song").submit((event) => {
event.preventDefault();
$.ajax({
type: "POST",
url: "ajax/",
data: {
"name": $(".top_song button").attr("name"),
csrfmiddlewaretoken: "{{ csrf_token }}",
},
success: function (response) {
console.log(response["likes"]);
},
error: function (re) {
console.log(re);
}
});
});
As said, in comment I have updated the JS file and I am sending the "button name Like1". In the views I am also checking it in views in request.POST["name"] == "Like1". Also I have updated the "URL" file and url part in JS file. Now the urls match. So instead of getting a Error: 404, I get Error: 403.
My Error
jquery.min.js:2 POST http://127.0.0.1:8000/guitar_blog/20/ajax/ 403 (Forbidden)
My Network Response
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="robots" content="NONE,NOARCHIVE">
<title>403 Forbidden</title>
<style type="text/css">
html * { padding:0; margin:0; }
body * { padding:10px 20px; }
body * * { padding:0; }
body { font:small sans-serif; background:#eee; color:#000; }
body>div { border-bottom:1px solid #ddd; }
h1 { font-weight:normal; margin-bottom:.4em; }
h1 span { font-size:60%; color:#666; font-weight:normal; }
#info { background:#f6f6f6; }
#info ul { margin: 0.5em 4em; }
#info p, #summary p { padding-top:10px; }
#summary { background: #ffc; }
#explanation { background:#eee; border-bottom: 0px none; }
</style>
</head>
<body>
<div id="summary">
<h1>Forbidden <span>(403)</span></h1>
<p>CSRF verification failed. Request aborted.</p>
</div>
<div id="info">
<h2>Help</h2>
<p>Reason given for failure:</p>
<pre>
CSRF token from POST has incorrect length.
</pre>
<p>In general, this can occur when there is a genuine Cross Site Request Forgery, or when
<a
href="https://docs.djangoproject.com/en/4.0/ref/csrf/">Django’s
CSRF mechanism</a> has not been used correctly. For POST forms, you need to
ensure:</p>
<ul>
<li>Your browser is accepting cookies.</li>
<li>The view function passes a <code>request</code> to the template’s <a
href="https://docs.djangoproject.com/en/dev/topics/templates/#django.template.backends.base.Template.render"><code>render</code></a>
method.</li>
<li>In the template, there is a <code>{% csrf_token
%}</code> template tag inside each POST form that
targets an internal URL.</li>
<li>If you are not using <code>CsrfViewMiddleware</code>, then you must use
<code>csrf_protect</code> on any views that use the <code>csrf_token</code>
template tag, as well as those that accept the POST data.</li>
<li>The form has a valid CSRF token. After logging in in another browser
tab or hitting the back button after a login, you may need to reload the
page with the form, because the token is rotated after a login.</li>
</ul>
<p>You’re seeing the help section of this page because you have <code>DEBUG =
True</code> in your Django settings file. Change that to <code>False</code>,
and only the initial error message will be displayed. </p>
<p>You can customize this page using the CSRF_FAILURE_VIEW setting.</p>
</div>
</body>
</html>
I have solved my Problem
My View
class MusicianDetailView(DetailView):
model = Musician
template_name = "guitar_blog/blog_detail.html"
@login_required
def post_likes(request):
song = Musician.objects.get(pk=int(request.POST.get("primary_key")))
user_id = int(request.POST.get("user_id"))
user_username = request.POST.get("username")
if "Like1" in request.POST.get("button_name") and user_username not in song.music_1_users.keys():
song.music_1_votes += 1
song.music_1_users[user_username] = user_id
song.save()
return JsonResponse({"final": song.music_1_votes, "req_name": "Unlike1", "inner_text": "Unlike"})
elif "Unlike1" in request.POST.get("button_name") and user_username in song.music_1_users.keys():
song.music_1_votes -= 1
song.music_1_users.pop(user_username)
song.save()
return JsonResponse({"final": song.music_1_votes, "req_name": "Like1", "inner_text": "Like"})
My URL
path('likes/', post_likes, name="post_likes"),
My Template
<form method="post" class="voting-setup" id="top-song-form">
{% csrf_token %}
<input type="hidden" class="username" value="{{ user.get_username }}">
<input type="hidden" class="user_id" value="{{ user.id }}">
<input type="hidden" class="user" value="{{ user }}">
<input type="hidden" class="primary-key" value={{ musician.pk }}>
{% if user.get_username in musician.music_1_users %}
<button name="Unlike1" type="button" class="like-button top-song-button">
<i class="fa-solid fa-guitar icon"
><span class="like-text top-button-inside-text">Unlike</span></i
>
</button>
{% else %}
<button name="Like1" type="button" class="like-button top-song-button">
<i class="fa-solid fa-guitar icon"
><span class="like-text top-button-inside-text">Like</span></i
>
</button>
{% endif %}
<span class="after-like" id="top-song-vote-count">Liked {{ musician.music_1_votes }}</span>
</form>
My JS File
$(".top-song-button").click(function (e) {
let data = {
"username": $(".username").val(),
"user_id": $(".user_id").val(),
"button_name": $(".top-song-button").attr("name"),
"primary_key": $(".primary-key").val(),
"user_set": $(".user").val(),
"csrfmiddlewaretoken": $("#top-song-form").serialize().split("=")[1],
}
e.preventDefault();
$.post('/likes/', data,
function (response) {
$("#top-song-vote-count").text("Liked " + response["final"]);
let my_button_text = document.querySelector(".top-button-inside-text");
let my_button = document.querySelector(".top-song-button");
my_button.name = response["req_name"];
my_button_text.innerText = response["inner_text"];
},
"json"
);
console.log(data);
});
Yes @shourav, you are right about the csrf_token mistake, but I did it in a different way as I was just passing "csrf_token" through the form, so the serialization only got the "csrf token". Also I did a hell lot of changes in this answer. Still thank you for the help @shourav.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.