简体   繁体   中英

JQuery Ajax success function not able to access Django View jsonresponse from view

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM