【发布时间】:2018-07-18 12:54:04
【问题描述】:
我正在使用 Django 开发一个博客站点。我的网站将允许用户对我的任何博客文章发表评论并相互回复,并将使用“线程化 cmets”结构显示(我还没有启动用户功能,只是 cmets)。我已经使用 django-mptt 让线程化 cmets 正常工作(至少目前是这样),但我不知道我正在采取的路线或步骤是否朝着正确的方向。我读过的几乎所有教程都只涉及到 cmets 的表面,并没有谈论 django 中的线程 cmets。我想要一些有经验/专业的建议,告诉我我可能做错了什么以及我可以做得更好。我最不想做的就是在投入数小时的工作之后,找出一种更容易接受的方式。
所以,这里列出了我需要澄清的内容:
-
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]
“已批准”已被注释掉,因为由于某种奇怪的原因,我收到“没有此类列:已批准”错误。
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'),
]
【问题讨论】:
-
谢谢!这些都是很好的建议。我正在寻找与 Django 2 兼容的东西。我相信 Mezzanine 只有在我没记错的情况下才使用 Django 1.8-1.10。但是,我一定会对此进行深入研究。
-
Mezzanine 已移植到 1.11(但你必须从 github 移植到
pip install最新版本),但据我所知还不是 2。 -
我认为你的问题有点太宽泛了。有多个问题或多或少是“我做得好还是不好?”您能否缩小您的问题范围,以便我们提供明确的答案?谢谢。
-
为什么要重新发明轮子?一切都已经完成了。 github.com/HonzaKral/django-threadedcomments
标签: python django django-mptt threaded-comments