Django - правильный способ реализации потоковых комментариев

Я разрабатываю блог-сайт с использованием Django. Мой сайт позволит пользователям комментировать любые сообщения в моем блоге, а также отвечать друг другу, и будет отображаться с использованием структуры "многопоточных комментариев" (я еще не запускал пользовательские функции, только комментарии). У меня есть многопоточные комментарии для правильной работы с использованием django-mptt (по крайней мере, на данный момент), но у меня НЕТ CLUE, если маршрут или шаги, которые я делаю, находятся в правильном направлении. Почти все уроки, которые я прошел, только поверхностно касаются комментариев, но не говорят о многопоточных комментариях в django. Я хочу получить опытный/профессиональный совет о том, что я могу делать неправильно и что я могу делать лучше. Последнее, что я хочу, - это узнать, что существует более приемлемый способ, после нескольких часов работы.

Итак, вот список того, что мне нужно прояснить:

  1. Джанго-mptt:

    • Я выбрал это, потому что я могу позволить себе более медленное время записи. Мой сайт будет больше читать, чем писать. Этот вариант подходит для моего случая? Есть ли лучшая альтернатива, о которой я не знаю?
    • Что мне делать, если на моем сайте много комментариев? Что я могу сделать, чтобы оптимизировать реструктуризацию дерева? Или мне лучше перейти к списку соседей?
    • Моя модель комментариев MPTT имеет ссылку на ForeignKey (для ответов). Это правильный путь? Или я должен создать отдельную модель ответа?
    • Я вставляю ответ на другой пользовательский комментарий в дереве, используя скрытый ввод в форме, который находится в тегах рекурсивного шаблона mptt, и возвращаю входное значение (которое является идентификатором комментария, для которого предназначен ответ) и устанавливаем родитель ответа на это входное значение. Это приемлемый метод?
  2. Несколько форм на одной HTML-странице

    • У меня есть две формы на моей странице блога HTML. Один, чтобы прокомментировать сообщение в блоге, и один, чтобы ответить на комментарий пользователя. Это принято? Или я должен создавать разные URL и просматривать функции для разных форм? Я сделал это таким образом, потому что хотел систему комментирования в стиле Reddit. Я не хочу, чтобы он заходил на другую страницу, чтобы комментировать или отвечать.
    • Если пользователь комментирует мою запись в блоге, скрытое значение ввода в форме ответа ничего не возвращает, поэтому я получаю сообщение об ошибке при попытке присвоить его переменной в функции views.py. Я использовал блок try/Кроме того, чтобы исправить это. Есть ли лучший способ обойти это?

Извините, если это нубские вопросы и мой пост очень длинный. Я просто хочу сделать все как можно лучше, используя реалистичные решения для начинающих. Любая обратная связь поможет. Спасибо! Вот мой код для моего блога.

models.py

    from django.db import models

    from mptt.models import MPTTModel, TreeForeignKey

    class Post(models.Model):
        """Blog post"""
        title = models.CharField(max_length=200)
        body = models.TextField()
       date_added = models.DateTimeField(auto_now_add=True)

        def __str__(self):
            return self.body[:50] + '...'

    class Comment(MPTTModel):
        """User comment"""
        post = models.ForeignKey(Post, related_name='comments',on_delete=models.CASCADE)
        parent = TreeForeignKey('self', null=True, blank=True, related_name='children',db_index=True, on_delete=models.CASCADE)

        user_comment = models.CharField(max_length=500, unique=True)
        date_added = models.DateTimeField(auto_now_add=True)
        # approved = models.BooleanField(default=False)

        class MPTTMeta:
            order_insertion_by = ['date_added']

        def __str__(self):
            return self.user_comment[:20]

"утвержден" закомментирован, потому что я получаю ошибку "нет такого столбца: утвержден" по какой-то странной причине.

forms.py

    from django import forms

    from .models import Post, Comment

    class CommentForm(forms.ModelForm):
        class Meta:
            model = Comment
            fields = ['user_comment']

views.py

    from django.shortcuts import render
    from django.http import HttpResponseRedirect
    from django.urls import reverse

    from .models import Post
    from .forms import CommentForm

    def posts(request):
        """Show all blog posts"""

        posts = Post.objects.order_by('-date_added')

        context = {
            'posts': posts
        }
        return render(request, 'posts/posts.html', context)

    def post(request, post_id):
        """Show single blog post"""

        post = Post.objects.get(id=post_id)
        comments = post.comments.all()

        if request.method != 'POST':
            comment_form = CommentForm()

        else:
            comment_form = CommentForm(data=request.POST)
            try:
                parent_id = request.POST['comment_id']
            except:
                pass
            if comment_form.is_valid():
                comment = comment_form.save(commit=False)
                comment.post = post
                comment.parent = comments.get(id=parent_id)
                comment.save()
                return HttpResponseRedirect(reverse('posts:post', args=[post_id]))

        context = {
            'post': post,
            'comment_form': comment_form,
            'comments': comments,
        }
        return render(request, 'posts/post.html', context)

post.html

    {% extends 'posts/base.html' %}

    {% block blog_content %}

        <h1>Post page!</h1>

        <h3>{{ post.title }}</h3>
        <h4>{{ post.date_added }}</h4>
        <p>{{ post.body }}</p>

        <form method="post" action="{% url 'posts:post' post.id %}">
          {% csrf_token %}
          {{ comment_form.as_p }}
          <button type="submit">Add comment</button>
        </form>

        {% load mptt_tags %}
          {% recursetree comments %}
          <h5>{{ node.date_added }}</h5>
          <p>{{ node.user_comment }}</p>
              <form method="post" action="{% url 'posts:post' post.id %}">
              {% csrf_token %}
              {{ comment_form.as_p }}
              <input type="hidden" name="comment_id" value="{{ node.id }}">
              <button type="submit">Reply</button>
              </form>
          {% if not node.is_leaf_node %}
            <div style="padding-left: 20px">
            {{ children }}
            </div>
          {% endif %}
          {% endrecursetree %}


    {% endblock %}

urls.py

    from django.urls import path

    from . import views

    app_name = 'posts'
    urlpatterns = [
        path('posts/', views.posts, name='posts'),
        path('posts/<int:post_id>/', views.post, name='post'),
    ]

Ответы

Ответ 1

Деревья MPTT отлично подходят для получения списка подузлов или количества узлов. Они являются дорогостоящими для добавления/вставки узлов, и стоимость увеличивается линейно с размером трех. Они предназначены для размещения данных дерева в реляционных базах данных. Кроме того, не дайте себя одурачить словами: "У меня будет гораздо больше чтений, чем записей". В идеале большинство операций чтения должны попадать в кеш, а не в базу данных под ним.

Почему бы не пропустить реляционную базу данных и пойти с базой данных NoSQL, которая может хранить собственные деревья? Для Django есть простая интеграция и практически любая база данных NoSQL, о которой вы можете подумать.