javascript Django + AJAX 评论

6vl6ewon  于 2023-01-07  发布在  Java
关注(0)|答案(1)|浏览(142)

我试图实现一个注解系统而不重新加载页面,但它不工作。注解只在页面重新加载后插入,但AJAX不工作。

<!-- COMMENT -->
    <div class="comment-section">
        <form action="{% url 'love:comment_urls' %}" method="POST" class='comment-form'>
            {% csrf_token %}
            <input type="hidden" name="post_id" value={{i.pk}}>
            {{ comment_form }}
            <button type="submit" name="submit_c_form">
                Опубликовать
            </button>
        </form>
    </div>
    <hr>

    <div class="comment_set">
        {% if i.quotes_comment.all %}
        {% for com in i.quotes_comment.all %}
        <b>{{ com.user }}:</b>
        {{ com.body }}
        {% endfor %}
        {% endif %}
    </div>
</div>

JS代码

// COMMENT 
$(document).ready(function () {
    $('.comment-form').submit(function () {
        event.preventDefault();
        console.log($(this).serialize());
        var url = $(this).attr('action')
        $.ajax({
            type: 'POST',
            url: url,
            data: $(this).serialize(),
            dataType: 'html',
            success: function (response) {
                console.log('Заработало')
                $('.comment-section').html(response['form']);
            },
            error: function (rs, error) {
                console.log(rs, error)

            }
        })

    })
})

正如我所说的,注解只在重启后插入,但是当我点击发布时,什么也没发生。如果你把dataType改为'json',解析器错误就会弹出。你能解释一下我做错了什么吗?

hof1towb

hof1towb1#

很难说你做错了什么,总的来说,代码丢失了。但是从你分享的内容来看,csrf_token不在AJAX请求header中。主要是,通过使用JQuery .serialize(),你试图以URL编码的符号传递数据,而不是作为JSON对象。
这个.serialize()输出将被用来传递数据作为一个查询字符串,通过将其附加到一个基本URL。并且,在视图中使用request.GET.get('parameter')访问它。相反,我们想要的是传递数据作为JSON,并通过request.body在视图级别访问它。
下面是一个完整的例子:
models.py

class Comment(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='comments')
    body = models.CharField(max_length=255)
    created_at = models.DateTimeField(auto_now_add=timezone.now())

class Post(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
    comments = models.ManyToManyField(Comment)
    title = models.CharField(max_length=30)
    body = models.CharField(max_length=255)
    created_at = models.DateTimeField(auto_now_add=timezone.now())

urls.py

from .views import post_detail, comment_create

app_name = 'love'

urlpatterns = [
    path('post/<int:pk>/', post_detail, name='post-detail'),
    path('comment/create/', comment_create, name='comment-create'),
]

两个视图,一个用于呈现模板,另一个用于处理AJAX请求。棘手的部分是试图找到一种与模板相同的format date方法。
views.py

from django.utils.formats import date_format
from django.shortcuts import get_object_or_404
from django.http import JsonResponse
import json

def post_detail(request, pk):
    post = get_object_or_404(Post, id=pk)
    has_commented = post.comments.filter(user=request.user).exists()

    context = {
        'post': post,
        'has_commented': has_commented
    }

    return render(request, 'post_detail.html', context)

def comment_create(request):
    data = json.loads(request.body)
    post_id = data['post_id']
    comment_body = data['body']

    comment = Comment.objects.create(user=request.user, body=comment_body)
    post = get_object_or_404(Post, id=post_id)
    post.comments.add(comment)

    created_at = date_format(comment.created_at, format='M. d, Y, h:m a', use_l10n=True)

    return JsonResponse({
        'user': comment.user.username, 
        'body': comment.body, 
        'created_at': created_at
        })

在第一个模板部分中,我们只显示数据,请注意,{# % if not has_commented % #}被注解掉了,在第一次编写代码时,我将注解数量限制为每个User一个。
邮件详情. html(HTML和DTL):

{% extends 'base.html' %}

{% block content %}
    <h1>{{post.title}}</h1>
    <h4>{{post.created_at}}</h4>
    <p>{{post.body}}</p>

    <hr>

    <div id="comment-div">
        {# % if not has_commented % #}
            <form action="{% url 'love:comment-create' %}" id="comment-form">
                <input type="hidden" id="post-id" value="{{post.id}}">
                <textarea id="comment-body" maxlength="255" rows="4" cols="50"></textarea>
                <br>
                <button type="submit" id="submit-comment">Comment</button>
            </form>
            <hr>
        {# % endif % #}
    </div>

    <div id="comment-list">
        <h2> Comments </h2>
        {% if post.comments.all %}
            {% for comment in post.comments.all %}
                <p>At {{comment.created_at|date:"M. d, Y, h:m a"}} {{comment.user}} commented:</p> 
                <p>{{comment.body}}</p>
            {% endfor %}
        {% endif %}
    </div>

第二部分包含<script>,负责添加新注解后模板中的每个事件。第一个函数用于从cookie中检索csrftoken值。
然后,在submit上单击我们收集数据并发送AJAX请求。注意几行。首先,其中csrf头名称设置为headers: {'X-CsrfToken': csrftoken}。其次,其中数据为converted to JSON stringdata: JSON.stringify({ post_id: post_id, body: body })
邮政_详细信息. html(JS):

<script>
        function getCookie(name) {
            let cookieValue = null;
            if (document.cookie && document.cookie !== '') {
                const cookies = document.cookie.split(';');
                for (let i = 0; i < cookies.length; i++) {
                    const 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;
        }

        $('#submit-comment').click( function (e) {
            e.preventDefault();
            var url = $('#comment-form').attr("action");
            var post_id = $('#post-id').attr("value");
            var body = $('#comment-body').val();
            const csrftoken = getCookie('csrftoken');

            $.ajax({
                method: "POST",
                url: url,
                headers: {'X-CsrfToken': csrftoken},
                data: JSON.stringify({ post_id: post_id, body: body }),
                success: function(comment) {
                    // $('#comment-div').prop("hidden", true);
                    $('#comment-body').val('');
                    $('#comment-list').append(
                        `<p>At ${comment.created_at} ${comment.user} commented:</p> 
                        <p>${comment.body}</p>`
                    );
                }
            });
        });
    </script>
{% endblock %}

最后,如果成功,清除body输入并通过将数据附加到<div id="comment-list">来更新模板。

相关问题