我目前正在通过 antonio mele 的《Django 示例》一书学习 Django,并且已经到了如何使用标签显示相同帖子的阶段。
它发生在我编写的代码中:
在 models.py 中编码
from django.db import models
# Create your models here.
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
from taggit.managers import TaggableManager
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager,self).get_queryset()\
.filter(status='published')
class Post(models.Model) :
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published')
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique_for_date= 'publish')
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name= 'blog_post')
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
objects = models.Manager()
published = PublishedManager()
tags = TaggableManager()
class Meta :
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post_detail',
args = [self.publish.year,
self.publish.month,
self.publish.day,
self.slug])
class Comment(models.Model):
post = models.ForeignKey(Post,
on_delete=models.CASCADE,
related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
class Meta:
ordering = ('created',)
def __str__(self):
return f'Comment by {self.name} on {self.post}'
Views.py
from django.db.models import Count
from django.shortcuts import render, get_object_or_404
from django.core.paginator import Paginator, EmptyPage, \
PageNotAnInteger
from django.views.generic import ListView
from django.core.mail import send_mail
from .models import Post, Comment
from .forms import EmailPostForm, CommentForm
from taggit.models import Tag
# Create your views here.
def post_list(request, tag_slug=None):
object_list = Post.published.all()
tag = None
if tag_slug:
tag = get_object_or_404(Tag, slug=tag_slug)
object_list = object_list.filter(tags__in=[tag])
paginator = Paginator(object_list, 3)
page = request.GET.get('page')
try:
posts = paginator.page(page)
except PageNotAnInteger:
posts = paginator.page(1)
except EmptyPage:
posts = paginator.page(paginator.num_pages)
return render(request,
'blog/post/list.html',
{'page' : page,
'posts' : posts,
'tag': tag})
class PostListView(ListView):
queryset = Post.published.all()
context_object_name = 'posts'
paginate_by = 3
template_name = 'blog/post/list.html'
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)
# Menampilkan comment yang aktif di postingan ini
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():
#buat objek comment tapi gak di simpan
new_comment = comment_form.save(commit=False)
# kasih tahu kalau postingan sekarang lg di comment
new_comment.post = post
# simpan comment di database
new_comment.save()
else:
comment_form = CommentForm()
# daftar postingan yang mirip
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_share(request, post_id):
# retrieve post id
post = get_object_or_404(Post, id = post_id, status = 'published')
sent = False
if request.method == 'POST':
form = EmailPostForm(request.POST)
if form.is_valid():
# Form fill isi nya udah bener
cd = form.cleaned_data
post_url = request.build_absolute_uri(
post.get_absolute_url()
)
subject = f"{cd['name']} recommendeds you read " \
f"{post.title}"
message = f"Read {post.title} at {post_url}\n\n" \
f"{cd['name']}\'s comments: {cd['comments']}"
send_mail(subject, message, '[email protected]', [cd['to']])
sent = True
else:
form = EmailPostForm()
return render(request, 'blog/post/share.html', {'post': post,
'form': form,
'sent': sent})
细节.html
{% extends "blog/base.html" %}
{% block title %}{{ post.title }}{% endblock %}
{% block content %}
<h1>{{ post.title }}</h1>
<p class="date">
Published {{ post.publish }} by {{ post.author }}
</p>
{{ post.body|linebreaks }}
<p>
<a href="{% url "blog:post_share" post.id %}">
Share this post.
</a>
</p>
<h2>Similar posts</h2>
{% for post in similar_posts %}
<p>
<a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
</p>
{% empty %}
Gak ada postingan yang mirip
{% endfor %}
{% with comments.count as total_comments %}
<h2>
{{ total_comments }} comment {{ total_comments|pluralize }}
</h2>
{% endwith %}
{% for comment in comments %}
<div class="comment">
<p class="info">
Comment {{ forloop.counter }} by {{ comment.name }}
{{ comment.created }}
</p>
{{ comment.body|linebreaks }}
</div>
{% empty %}
<p>There are no comments yet.</p>
{% endfor %}
{% if new_comment %}
<h2>Your comment has been added</h2>
{% else %}
<h2>Add a new comment</h2>
<form method="post">
{{ comment_form.as_p }}
{% csrf_token %}
<p>
<input type="submit" value="Add Comment">
</p>
</form>
{% endif %}
{% endblock %}
我真的不知道我应该改什么,因为我觉得是按照书上的写的。所以,请各位知道这行代码有什么问题的朋友帮忙
谢谢
blog
应用程序的Post
模型的表名称:blog_post
和相关字段author
的related_name='blog_post'
之间存在名称冲突,因为您忘记使用复数形式(在blog_post
之后缺少's'字母
).固定Post
模型:
class Post(models.Model):
...
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts')
检查您的数据库
blog_post
表是否有tags
字段。如果没有,您可以重新运行迁移,或者由于您正在学习 Django,您可以从一个新的数据库开始。