Zorgan
Zorgan

Reputation: 9123

How to make infinite threaded comments

My current code allows me to render a queryset of Comments (parent comments) as well as replies to those comments. But i'm unable to render replies to those replies. My goal is to have an infinite reply system. Here's my code:

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)
    parent_comment = models.ForeignKey('self', related_name='replies', related_query_name='replies', blank=True, null=True)
    comment_text = models.TextField(max_length=350, blank=True, null=True)
    timestamp = models.DateTimeField(default=timezone.now, blank=True)
    children = models.IntegerField(default=0)

    def __str__(self):
        return str(self.comment_text)

my parent comment view:

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')
        comment_length = len(str(ajax_comment))
        if comment.is_valid() and request.user.is_authenticated:
            comment = Comment.objects.create(comment_text=ajax_comment, destination=id, user=request.user)
            username = str(request.user)
            return JsonResponse({'text': ajax_comment, 'text_length': comment_length,
                                 'username': username, 'id': comment.id})
        else:
            return HttpResponse()

and my reply view:

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')
        parent = Comment.objects.get(id=parent_id)
        parent.children += 1
        parent.save()
        if comment.is_valid() and request.user.is_authenticated:
            comment = Comment.objects.create(comment_text=reply_text, destination=id, user=request.user, parent_id=parent_id, parent_comment=parent)
            username = str(request.user)
            return JsonResponse({'reply_text': reply_text, 'username': username})
        else:
            return HttpResponse()

ajax calls

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()
    console.log('this:', c);

$.ajax({
    type: 'POST',
    url: '/user_comment/',
    data: {
        text: $(this).find('.comment_text').val(),
        id: path,
        csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),
},
    success: function(data) {
        if(data.text == '') {
            console.log('Cannot submit blank comment');
        } else {
            //console.log('')
            $('.commentsContainer hr').prepend("<div class='comment_div'><div class='left_comment_div'>" +
                "<div class='username_and_votes'><h3><a class='username_foreign'>" + data.username +
                "</a></h3></div><br><p>" + data.text +
                "</p></div></div>");
        }}

});

});

// reply comment

    $(document).on('submit', '.reply_comment_form', 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' style='display: inline-block;'><div class='left_comment_div'>" +
                "<div class='username_and_votes'><h3><a href='#' class='username_foreign'>" + data.username +
                "</a></h3><br><p>" + data.reply_text +
                "</p></div></div>");

            }

        });


    });

and the comments html

<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>
        </div>
        {% for reply in i.replies.all %}
            <div class='comment_div new_comment' data-comment_id="{{ reply.id }}">
            <div class="left_comment_div">
                <div class="username_and_votes">
                    <h3><a class='username_foreign'>{{ reply.user }}</a></h3>
                </div>
                <br>
                <p>{{ reply.comment_text }}</p>
            </div>
        </div>
        {% endfor %}
    {% endfor %}
</div>

If someone could give me advice how to implement endless replies from the code I currently have that would be great.

Upvotes: 1

Views: 682

Answers (1)

Sayse
Sayse

Reputation: 43300

You need to turn your comments loop into a separate template

{% for i in comments %}
    <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>
    </div>
    {% include 'comments_template.html' with comments=i.replies.all %}
{% endfor %}

Then you just call this where you need it with

{% include 'comments_template.html' with comments=comment_list %}

Upvotes: 2

Related Questions