关于在Django中创建线程评论系统的建议

时间:2017-02-01 22:23:14

标签: jquery ajax django django-models

我正在制作我的Django评论系统。到目前为止我所做的是:

  • AJAX初始评论(附加父评论,无页面刷新/保存到数据库)

  • Django初始评论(能够在页面刷新后呈现上面的父评论)

  • AJAX第一回复(附加第一个回复,没有页面刷新/保存到数据库)

现在这就是我要做的事情。由于我想拥有一个线程(无尽的)评论系统,用户可以不断地相互回复,我想在开始之前清楚地了解我将如何做到这一点。我的Comment模型如下所示:

class Comment(models.Model):
    user = models.ForeignKey(User, blank=True, null=True)
    destination = models.CharField(default='1', max_length=12, blank=True)
    parent_id = models.IntegerField(default=0)
    comment_text = models.TextField(max_length=350, blank=True, null=True)

    def __str__(self):
        return self.comment_text

我的AJAX调用如下所示:

var str = window.location.href.split('?')[0];
var path = str.split("/")[4];

$('.comment_form').on('submit', function(e) {
e.preventDefault();

var c = $(this).find('.comment_text').val()

$.ajax({
    type: 'POST',
    url: '/user_comment/',
    data: {
        text: $(this).find('.comment_text').val(),
        id: path,
        csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),
},
    success: function(data) {
            $('.commentsContainer hr').prepend("<div class='comment_div'><div class='left_comment_div'>" +
                <h3><a href='#' class='username'>" + data.username +
                "</a></h3><p>" + data.text +
                "</p><a href='#'><span class='comment_delete'>x</span></a></div>");
        }

});

});

评论模板

<div class="commentsContainer">
    <form action="" class="comment_form">{% csrf_token %}
        {{ comment.comment_text|add_class:"comment_text" }}
        {{ comment.id }}
        <input type="submit" value="Comment" class="comment_submit">
    </form>
    <hr>
    {% for i in comment_list %}
        <div class='comment_div' data-comment_id="{{ i.id }}">
            <div class="left_comment_div">
                <div class="username_and_votes">
                    <h3><a class='username_foreign'>{{ i.user }}</a></h3>
                </div>
                <br>
                <p>{{ i.comment_text }}</p>
            </div>

                <a class="reply">reply</a><a class="cancel_comment">cancel</a>
                <span><a class="comment_delete" data-comment_id="{{ i.id }}">x</a></span>
        </div>
    {% endfor %}
</div>

这是我的观点:

def user_comment(request):
    if request.is_ajax():
        comment = CommentForm(request.POST or None)
        ajax_comment = request.POST.get('text')
        id = request.POST.get('id')

        if comment.is_valid():
            comment = Comment.objects.create(comment_text=ajax_comment, destination=id, user=request.user)
            comment.save()
            username = str(request.user)
            return JsonResponse({'text': ajax_comment,'username': username, 'id': comment.id})

现在我也开始尝试回复,但我可能没有采用正确的方式,所以请随意忽略以下代码,因为可能有更好的方法。有了回复的jQuery前端,我不得不做一个单独的功能,因为使用相同的功能是行不通的。我还必须制作一个onclick才能使其正常运行。因此,当用户点击回复按钮时,它会克隆最初的comment_form并在他们回复的评论后附加:

$('.reply').on('click', function(e) {
    var clone = $('.comment_form').clone();
    parent_id = $(this).closest('.comment_div').data('comment_id');
    $(this).closest('.comment_div').after(
        clone
    );
    clone.addClass('reply_comment_form').removeClass('comment_form');
    clone.attr('onclick', 'reply_comment()');
    clone.data('comment_id', parent_id);

    $(this).next().css('display', 'inline-block');
    $(this).css('display', 'none');

});

//然后当他们提交实际回复评论时:

function reply_comment() {
    $('.reply_comment_form').on('submit', function (e) {
        e.preventDefault();
        parent_id = $('.reply_comment_form').data('comment_id');

        $.ajax({
            type: 'POST',
            url: '/comment_reply/',
            data: {
                reply_text: $(this).find('.comment_text').val(),
                parent_id: parent_id,
                id: path,
                csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),
            },
            success: function(data) {
                $('.reply_comment_form').replaceWith("<div class='comment_div new_comment'><div class='left_comment_div'>" +
                "<h3><a href='#' class='username'>" + data.username +
                "</a></h3> + data.reply_text +
                "</p><a href='#'><span class='comment_delete'>x</span></a></div>");
                $('.new_comment').css({
                    'width': '72%',
                    'margin': '0 70 10 0',
                    'float': 'right',
                });
                 $('.new_comment').next().css('clear', 'both');
                 $('.new_comment').prev().find('.cancel_comment').css('display', 'inline-block')
                     .find('.cancel_comment').css('display', 'inline-block');
            }

        });


    });
}

回复视图:

def comment_reply(request):
    if request.is_ajax():
        comment = CommentForm(request.POST or None)
        reply_text = request.POST.get('reply_text')
        id = request.POST.get('id')
        parent_id = request.POST.get('parent_id')

        if comment.is_valid():
            comment = Comment.objects.create(comment_text=reply_text, destination=id, user=request.user, parent_id=parent_id)
            comment.save()
            username = str(request.user)
            return JsonResponse({'reply_text': reply_text, 'username': username})

我已将第一次回复的parent_id等同于原始评论的comment.id。但正如我所说,这样的链接可能不是最好的方式,那么我如何链接评论及其回复呢?我是否在Comment模型中创建了另一个字段?我可以以某种方式使ForeignKey引用回相同的Comment模型吗?在呈现回复的回复方面,它如何在模板中起作用,因为它是连续的。 建议很高兴。

1 个答案:

答案 0 :(得分:0)

  

我能以某种方式让一个ForeignKey引用回来   评论模型?

class Comment(models.Model):
     parent = models.ForeignKey('self', related_name='children')
     text = models.TextField(max_length=350, blank=True)
  

在渲染方面,它如何在模板中起作用   答复的答复,因为它是连续的

您可以执行以下操作:制作模板comment.html

{% for comment in comments %}
    <p>{{ comment.text }}</p>
    {% if comment.children %}
        {% include "comment.html" with comments=comment.children %}
    {% endif %}
{% endfor %}

但是你应该在视图中进行预取以减少查询次数。我不确定如何在任何深度上做到这一点。但对于预定义的深度,可以这样做:Comment.objects.prefetch_related('children__children__children')