Django说数据库没有tags这一列,查看了数据库确实是。
这时候发现就算在post的模型里面再改做迁移也不行,问题代码出现在视图文件的post_detail:
def post_detail(request, year, month, day, post):
post = get_object_or_404(Post, slug=post,
status='published',
publish__year=year,
publish__month=month,
publish__day=day)
# List of active comments for this post
comments = post.comments.filter(active=True)
new_comment = None
if request.method == 'POST':
# A comment was posted
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
# Create Comment object but don't save to database yet
new_comment = comment_form.save(commit=False)
# Assign the current post to the comment
new_comment.post = post
# Save the comment to the database
new_comment.save()
else:
comment_form = CommentForm()
# List of similar posts
post_tags_ids = post.tags.values_list('id', flat=True)
similar_posts = Post.published.filter(tags__in=post_tags_ids)\
.exclude(id=post.id)
similar_posts = similar_posts.annotate(same_tags=Count('tags'))\
.order_by('-same_tags','-publish')[:4]
return render(request,
'blog/post/detail.html',
{'post': post,
'comments': comments,
'new_comment': new_comment,
'comment_form': comment_form,
'similar_posts': similar_posts})
好家伙,我们继续用列表推导式重写这个函数。
def post_detail(request, year, month, day, post):
post = get_object_or_404(Post, slug=post,
status='published',
publish__year=year,
publish__month=month,
publish__day=day)
# 评论列表
comments = post.comments.filter(active=True)
new_comment = None
if request.method == 'POST':
# 提交一个评论
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid(): # 有效
new_comment = comment_form.save(commit=False) # 创建一个评论对象,保存到数据库中
new_comment.post = post
new_comment.save()
else:
comment_form = CommentForm
# 获取与当前博文有相同标签的其他博文,按发布日期降序排序
similar_posts = [p for p in Post.published.exclude(id=post.id).all() if
any(tag in post.tags.all() for tag in p.tags.all())][:4]
# 分页逻辑
paginator = Paginator(similar_posts, 4) # 4个一页
page = request.GET.get('page')
try:
similar_posts = paginator.page(page)
except PageNotAnInteger:
similar_posts = paginator.page(1)
except EmptyPage:
similar_posts = paginator.page(paginator.num_pages)
return render(request,
'blog/post/detail.html',
{'post': post,
'comments': comments,
'new_comment': new_comment,
'comment_form': comment_form,
'similar_posts': similar_posts})
问题解决。
详细解释一下这个列表推导式。
similar_posts = [p for p in Post.published.exclude(id=post.id).all() if any(tag in post.tags.all() for tag in p.tags.all())][:4]
-
for p in Post.published.exclude(id=post.id).all()
: 遍历Post.published
中除了当前博文以外的所有博文。 -
if any(tag in post.tags.all() for tag in p.tags.all())
: 这里我们使用any()
函数和内部的生成器表达式来检查是否有任何标签在p.tags.all()
中也存在于post.tags.all()
中。如果有,这意味着p
和post
有至少一个相同的标签。 -
[:4]
: 最后,我们通过切片只取前4个满足条件的博文。 -
最后效果如图