Django-实现线程注释的正确方法 - python

我正在使用Django开发博客站点。我的网站将允许用户在我的任何博客文章中发表评论并互相回复,并使用“线程评论”结构进行显示(我尚未启动用户功能,仅是评论)。我已经使用django-mptt使线程注释正常工作(至少现在是这样),但是如果我选择的路线或方向正确,我将一无所知。当涉及到注释时,我所经历的几乎所有教程都只是从头开始,而没有涉及django中的线程注释。对于我可能做错了什么以及我可以做得更好的事情,我需要一些经验丰富/专业的建议。我要做的最后一件事是,经过数小时的工作,发现有一种更可接受的方法。

所以,这是我需要澄清的清单:

django-mptt:

我之所以选择它,是因为我负担得起更慢的写入时间。我的网站的读写次数更多。这个选项适合我的情况吗?有我不知道的更好的选择吗?
如果我的站点确实有很多评论活动,该怎么办?我该怎么做才能优化树的重组?还是我最好切换到邻接表?
我的MPTT注释模型具有一个引用到其自身的ForeignKey(用于答复)。这是正确的方法吗?还是应该创建一个单独的回复模型?
我在树中插入对另一个用户的评论的回复的方法是在mptt递归模板标记内的表单中使用隐藏的输入,然后返回输入值(这是回复所针对的评论的ID)并进行设置该输入值的回复的父级。这是公认的方法吗?

一个HTML页面上有多种表单

我的博客文章HTML页面上有两种形式。一个在博客上发表评论,一个在回复用户评论。这被接受吗?还是应该创建不同的URL并查看不同形式的函数?我这样做是因为我想要Reddit风格的评论系统。我不希望它必须转到其他页面来发表评论或回复。
如果用户在我的博客文章中发表评论,则答复表单中的隐藏输入值将不返回任何内容,因此在尝试将其分配给views.py函数中的变量时出现错误。我使用了try / except块来修复它。有没有更好的办法解决这个问题?

很抱歉,如果这些不是菜鸟问题,并且我的帖子这么长。我只想为初学者使用切合实际的解决方案,以最好的方式做事情。任何反馈将有所帮助。谢谢!这是我的博客应用程序的代码。

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]

由于某些奇怪的原因,我收到“没有这样的专栏:已批准”错误,因此将“已批准”注释掉。

表格

    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'),
    ]

python大神给出的解决方案

MPTT树非常适合获取子节点列表或节点数。它们增加/插入节点的成本很高,并且成本随着三个节点的大小线性增加。它们旨在使树数据适合关系数据库。另外,不要被“我的读写要多得多”所骗。理想情况下,大多数读取应命中缓存,而不是缓存下的数据库。

为什么不跳过关系数据库,而选择可以原生存储树的NoSQL数据库呢? Django和几乎每个NoSQL数据库都可以轻松集成。

post_save信号未调用 - python

我已经阅读了所有相关问题。我有两个Django项目,信号在一个项目中可以正常工作,但在第二个项目中却不能工作(我只是复制粘贴代码并分别更改了名称)。我有一个带有订单模型的订单应用。应用程序包含在INSTALLED_APPS设置中。我在apps.py中有应用程序配置:from django.apps import AppConfig class OrdersC…

用大写字母拆分字符串,但忽略AAA Python Regex - python

我的正则表达式:vendor = "MyNameIsJoe. I'mWorkerInAAAinc." ven = re.split(r'(?<=[a-z])[A-Z]|[A-Z](?=[a-z])', vendor) 以大写字母分割字符串,例如:'我的名字是乔。 I'mWorkerInAAAinc”变成…

Celery任务不会通过记录器重要消息向管理员发送电子邮件 - python

每次调用logger.critical,我的celery任务都不会向应用程序管理员发送电子邮件。我正在构建Django应用程序。我项目的当前配置允许应用程序的管理员在每次创建logger.critical消息时都收到一封电子邮件。设置起来非常简单,我只是遵循了两个项目(celery和Django)的文档。出于某种原因(我不确定),在celery任务中运行的代…

字符串文字中的正斜杠表现异常 - python

为什么S1和S2在撇号位置方面表现不同?S1="1/282/03/10" S2="4/107/03/10" R1="".join({"N\'" ,S1,"\'" }) R2="".join({"N\'…

PyCharm中Django的文档字符串中未解决的引用 - python

我在Django的专案中使用Google Style Python Docstrings like in this Example。当我创建一个类并在文档字符串中使用属性符号时,Pycharm总是说-“未解决的引用”。class Post(models.Model): """ Class for posts. Attribute…