tentekoten
@tentekoten

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Djangoを使ってformをajaxする方法

Djangoでのfromをajaxする方法

Djangoでweb開発の勉強をしています。投稿を非同期通信でdjangoにデータを送信する仕組みを作っています。jqueryでajaxしようとしたいのですがurlやデータが文字化けしてしまい、上手くデータを送れません。Djangoで受け取った{{form.as_p}}をajaxのdataに入れる方法と文字化けしない方法を教えて欲しいです。

Invalid or unexpected token

Uncaught SyntaxError: Invalid or unexpected token

データを受け取った後に文字化けしたデータが返されてしまう
スクリーンショット 2021-11-25 17.22.53.png

post.html

{% block contents %}
<main>
<div class="container">

  <form id="content_form" action="{% url 'post:posts' to_user.id %}" method="post">
    {% csrf_token %}
    <p>{{ form.as_p }}</p>
    <button type="submit">送信</button>
  </form>

  <div id="posts">
  <!-- UserのPost一覧 -->
  {% for post in posts reversed %}
  <div class="post">
    <span class="content">{{post.content}}</span>
    <span class="count_{{post.id}}">{{post.good_count}}</span>
    <button class="good" name="{{post.id}}" type="button">good</button>
    <span class="error_{{post.id}}"></span>
  </div>
  {% endfor %}
  </div>
  </div>
  </main>

  {% block extrajs %}
  <script>
    var i = 'Hello World'
    console.log(i)

    window.addEventListener('DOMContentLoaded', function(){
        $('#content_form').on('submit', function(e) {
          e.preventDefault();
          var form = $(this);
          $.ajax({
              url: form.prop("action"),
              method: form.prop("method"),
              dataType: 'json',
              data: {
                  content: '{{form.as_p}}',
              },
              success:function(response){
                  const p = $('.test1'.text(response.content));
                  const c = $('.test2'.text(response.good_count));
                  $('.test').prepend(p);
                  $('.test').prepend(c);
                  alert(data);
                  $('#content_form').val('');
              },
          })
        })
    })
  </script>
  {% endblock %}

  <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
{% endblock %}
  </body>

views.py

from django.shortcuts import render
from django.shortcuts import redirect
from .forms import PostForm, CreatePostForm
from django.contrib.auth.decorators import login_required
from .models import Post, Good
from accounts.models import CustomUser
import json
from django.http import JsonResponse

@login_required
def createpost(request, pk):
    # <int:id>の取得をする
    to_user = CustomUser.objects.get(pk=pk)

    if (request.method == 'POST'):
        # postを作成する
        p = Post()
        p.owner_id = request.user.pk
        # page/<int:id>を引っ張ってきてto_userにする
        p.to_user = to_user
        p.content = request.POST.get('content')
        p.save()
        # データを返す
        d = {
            'content': p.content,
            'good_count': p.good_count,
        }
        return JsonResponse(d)

    # UserへのPostを取得
    posts = Post.objects.filter(to_user=pk).order_by('good_count')

    # 共通処理
    params = {
            'login_user':request.user,
            'form':CreatePostForm,
            'to_user':to_user,
            'posts':posts,
        }

    return render(request, 'post.html', params)

自分で試したこと

Cookieを受け取れてないのかと思い、調べてCookieを取得するシステムも試してみましたが、JQuery in not definedというエラーが出てこれも上手く行きませんでした。あらゆるエンコードを指定するコードも設定してみましたが、文字化けは変わらないままでした。

0

1Answer

文字化けしたように見えるデータについて、 \u3042 をエスケープシーケンスで表現した値です。表記が違うだけで正しいデータになっています。

デフォルトでは ASCII 範囲の文字(半角英数字と一部の記号)以外はエスケープされますが、そうしたくない場合は JsonResponse に以下のオプション引数を渡してください。

return JsonResponse(d, json_dumps_params={'ensure_ascii': False})

次に、

Uncaught SyntaxError: Invalid or unexpected token

これは JS のどこか構文エラーがあることを表します。 content: '{{form.as_p}}' でデータを埋め込んだせいかもしれません。

また form.as_p を ajax で送ったとして、それは Django によって埋め込まれたデータを送り返すだけなので意味がありません。ユーザーが HTML フォームに入力された内容を送りたいなら以下のようにしてください。

content: new FormData($('#content_form').get(0))
1Like

Comments

  1. @tentekoten

    Questioner

    ご返信ありがとうございます!試してみましたが、Uncaught TypeError: Illegal invocationとエラーが出てしまいました。調べてみたら不正な呼び出しと書いてあったのですが、どこか他がおかしいでしょうか?
  2. FormData を送るには jQuery.ajax() に以下のオプションも渡す必要があるようです。
    processData: false,
    contentType: false,
  3. 1つ目のエラーは謎です。 /posts/ 以降の部分が
    {% url 'post:posts' to_user.id %}
    をエスケープしたものに似ていますね('post:posts' ではなく 'posts' になっていますが)。
    post.html の Django テンプレートを部分を解釈せずにただの HTML として表示したうえでフォームを送信したらそんなリクエストが飛ぶかも?という感じですが、よく分かりません。

    2つ目のエラーで出ている 500 (Internal Server Error) は Django 側でエラーが起きているという意味です。そちらのログを見てください。
  4. @tentekoten

    Questioner

    django.db.utils.IntegrityError: NOT NULL constraint failed: post_post.contentこのようなエラーが渡されていました。dataをform.val()で空の値を渡してみたら上手くアラームが発生し、データベースにも空文字が追加されていました。やはりformの中身を取り出すとこでエラーが発生しているようです、、、
  5. だとすると JSON を POST したほうがよさそうですね。

    processData: false,
    contentType: false,

    を消したうえでデータを

    data: {
    content: $("#id_content").val(),
    good_count: $("#id_good_count").val(),
    },

    にするといけるんじゃないかと思います。

    {{ form.as_p }} で埋め込んだフォームの input 要素には id_<フィールド名> なる ID が振られることを利用しています。 https://docs.djangoproject.com/en/3.2/topics/forms/#form-rendering-options
  6. @tentekoten

    Questioner

    実装できました!!本当にありがとうございました!!

Your answer might help someone💌