質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.48%

Djangoでリスト表示すると最初の項目でしかAjaxでうまく値を渡せない

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 610

score 16

前提・実現したいこと

Djangoでフォロー機能をAjaxを用いて作成したいと思っています。
現在は以下のようなコードとなっていて、ユーザーの一覧とその横にフォローボタンが配置されています。
これでフォローボタンを押すとフォローすることができるのですが、正常に動くのは一番上に表示されたユーザーのみで、二番目以降のユーザーをフォローしようとすると、404が表示されてしまいます。
viewの一番上のget_object_or_404で引っ掛かったのかと思い、viewの処理が始まるところを確認すると、最上部のユーザーはuser_pkの値が渡ってるのに対し、2番目以降はNoneとなっていました
全てのユーザーで最上部と同じような処理できるように、2番目以降のpost_pkを渡すにはどうすればよいのでしょうか?

該当のソースコード

{% for user in all_user %}

     <h3>{{ user.username }}</h3>
    <p>request_user_pk:{{ request_user.pk }}</p>
    <p>follow_user_pk:{{ user.pk }}</p>

     <form id="follow_user" action="{% url 'follow' %}" method="POST">

        <input type='hidden' value={{ user.pk }} id='user_pk'>

         <button type="submit"><span id='good_counts'>フォロー</span></button>
        {% csrf_token %}
     </form>

{% endfor %}

<script src="{% static 'js/follow_user.js' %}"></script>
def users_follow(request):
    user = get_object_or_404(CustomUser, pk=request.POST.get('user_pk'))
    follow = FollowRelation.objects.filter(to_user=user, from_user=request.user)
    if follow.exists():
        follow.delete()
        status = 'フォロー解除'
    else:
        FollowRelation.objects.create(to_user=user, from_user=request.user)
        status = 'フォローする'
    d = {
        'follow_status': status
    }
    return JsonResponse(d)

外部のfollow_user.jsはこちらです

document.getElementById('follow_user').addEventListener('submit', e => {
    e.preventDefault();

    const url = document.getElementById('follow_user').action;
    const user_id = document.getElementById('user_pk').value;
    alert(user_id)
    fetch(url, {
        method: 'POST',
        body: `user_pk=${user_id}`,
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
            'X-CSRFToken': csrftoken,
        },
    }).then(response => {
        return response.json();
    }).then(response => {
        alert(response.follow_status)
        $('#good_counts').empty();
        const p = $('<span>', {text: response.follow_status});
        $('#good_counts').append(p);
    }).catch(error => {
        console.log(error);
    });
});
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

Djangoに詳しいわけではないですが、HTMLとJavaScriptの問題です。
ID属性(今回はfollow_userですかね)は同一ページに重複不可です。

最初に宣言されたものだけが有効になるので、「一番最初のものしか反映されない」で合ってます。

ループ内で作るなら連番でも良いので別個にID振るか、
ボタンのクリックイベント取る時に楽になるようにCLASS振ってください。

・・・そもそもですが、Ajaxという前提ならボタンはsubmitでなくていいですね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/03/28 15:35

    回答ありがとうございます。
    連番で別個にIDを振ろうと思うのですが、そうなるとjsファイルではどう指定すればいいのでしょうか。初心者ですみません。

    キャンセル

  • 2020/03/28 15:46

    Ajaxですよね。
    今の作りだとformのサブミットイベントになってるので、ボタンのクリックイベントにすればよいと思います。
    そちらもidから取るのではなくクラスなどを振って、それぞれとるような形です。
    https://www.mitsue.co.jp/knowledge/blog/frontend/201805/24_0917.html

    キャンセル

  • 2020/03/29 22:12

    できました!!!
    参考のURLもとても勉強になりました、助けていただきありがとうございました。

    キャンセル

  • 2020/03/30 05:41

    解決されたようで何よりです

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る