上一篇‘博客系统’的博客还没有实现评论,按标签搜索、按日期搜索、按分类搜索的功能,这篇博客主要是对以上功能的增加。
增添评论
第一步:新建app:comment,在主setting.py中添加新app,修改主urls.py文件
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'',include('blog.urls')),
url(r'',include('comments.urls')),
]
第二步:编写评论的数据库表单
from django.contrib.auth.models import User
from django.db import models
# Create your models here.
from blog.models import Post
class Comment(models.Model):
user =models.ForeignKey(User,verbose_name='用户')
email = models.EmailField(verbose_name='电子邮箱')
text = models.TextField(max_length=255,verbose_name='评论正文')
# auto_now_add=True 自动create_time为最新一次更改评论信息的时间
create_time = models.DateTimeField(auto_now_add=True,verbose_name='创建时间')
post = models.ForeignKey(Post)
class Meta:
verbose_name = '评论'
verbose_name_plural = '评论'
def __str__(self):
return self.text[:4]
第三步:编写评论的路由comment.urls.py和comment.views.py
# comment.views.py
from django.shortcuts import render, get_object_or_404,redirect
# Create your views here.
from blog.models import Post
from comments.forms import CommentForm
def post_comment(request, id):
# 1. 获取用户选择的博客
post = get_object_or_404(Post, id=id)
# 2. 如果用户提交评论
if request.method == 'POST':
print(request.POST)
form = CommentForm(request.POST)
# 2.1 判断表单是否合法
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
# 2.2 如果不合法,则提交错误信息
else:
return render(request, 'blog/detail.html',
context={
'errors': form.errors
})
# 3. 如果不是POST请求,访问用户详情页
return redirect(post.get_url())
# comment.urls
from django.conf.urls import url, include
from django.contrib import admin
from comments import views
app_name = 'comment'
urlpatterns = [
url(r'^comment/blog/(?P\d+)/$',views.post_comment,name='post_comment'),
]
第四步:编写评论表单
# 同步与数据库评论的形式
from comments.models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['user','email','text']
第五步:修改HTML文件中关于评论的部分
发表评论
自定义标签
实现按标签搜索、按日期搜索、按分类搜索的功能
第一步:自定义标签
- 准备(必需)工作:
在某个app下创建一个名为templatetags(必需,且包名不可变)的包。假设我们在名为blog的app下创建了一个templatetags的包,并在该包下创建了一个名为blog_tags的文件.
确保settings文件中的INSTALLD_APPS内必须含有该app
修改setting.py有关时间显示的部分
# TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
#如果setting中配置USE_TZ=True则输出的是UTC时间(naive time),
# 如果setting中配置USE_TZ=False,则该输出时间与datetime.datetime.now()完全相同
# USE_TZ = True
USE_TZ = False
2. 接下来在blog_tags文件中写入如下几行
from django import template
register = template.Library()
3. 在模板中使用{% load %} 标签装载自定义标签或者装饰器
from django import template
from django.db.models import Count
from blog.models import Post, Category, Tag
register = template.Library()
@register.simple_tag
def get_recent_posts(num=3):
return Post.objects.all().order_by('-create_time')[:num]
@register.simple_tag
def archives():
return Post.objects.dates(field_name='create_time',
kind='month',
order='DESC')
@register.simple_tag
def get_category():
return Category.objects.annotate(num_posts=Count('post')).filter(num_posts__gt=0)
@register.simple_tag
def get_tags():
# return Tag.objects.all()
return Tag.objects.annotate(num_posts = Count('post'))
第二步: 编写标签查找的路由和视图函数
路由
#blog.urls.py
from django.conf.urls import url
from django.contrib import admin
from blog import views
app_name = 'blog'
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'blog/(?P\d+)/$', views.detail, name='detail'),
url(r'^archive/(?P\d{4})/(?P\d{1,2})/', views.archive, name='archive'),
url(r'^category/(?P\d+)/', views.category, name='category'),
url(r'^tag/(?P\d+)/', views.tag, name='tag'),
url(r'^search', views.search, name='search')
]
视图函数
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
# Create your views here.
from markdown import markdown
from blog.models import Post, Tag
from comments.forms import CommentForm
def index(request):
# return HttpResponse('ok index!')
posts = Post.objects.all()
return render(request,'blog/index.html',context={
'posts':posts
})
def detail(request,id):
# return HttpResponse('ok,%s detail' %(id))
post = Post.objects.get(id=id)
post.add_views()
form = CommentForm()
comments = post.comment_set.all()
post.body = markdown(post.body,
extensions=['markdown.extensions.extra',
'markdown.extensions.codehilite',
'markdown.extensions.toc', ],
output_format='html')
return render(request,'blog/detail.html',context={
'post':post,
'comments':comments,
'form':form,
})
def archive(request,year,month):
posts = Post.objects.filter(
create_time__year=year,
create_time__month=month
).order_by('-create_time')
return render(request,'blog/index.html',context={
'posts':posts
})
def category(request,id):
posts = Post.objects.filter(category_id=id)
return render(request,'blog/index.html',
context={
'posts':posts
})
def tag(request,id):
tag = get_object_or_404(Tag,id=id)
posts = Post.objects.filter(tags=tag).order_by('-create_time')
return render(
request, 'blog/index.html',
context={
'posts': posts
}
)
def search(request):
query = request.GET.get('query',None)
posts = Post.objects.filter(
Q(title__icontains=query) |
Q(body__icontains=query)
)
if not posts:
return render(request,'blog/index.html',
context={
'posts':posts,
'message':'没有找到相关信息'
}
)
else:
return render(request, 'blog/index.html',
context={
'posts': posts
}
)
第三步:修改Html文件,仅截取部分代码
这里在博客详情页需要显示的是博客的结构(目录),添加显示目录的代码
修改视图函数
def detail(request,id):
# return HttpResponse('ok,%s detail' %(id))
post = Post.objects.get(id=id)
post.add_views()
form = CommentForm()
comments = post.comment_set.all()
# post.body = markdown(post.body,
# extensions=['markdown.extensions.extra',
# 'markdown.extensions.codehilite',
# 'markdown.extensions.toc', ],
# output_format='html')
md = Markdown(
extensions=['markdown.extensions.extra',
'markdown.extensions.codehilite',
'markdown.extensions.toc', ],
output_format='html'
)
# Convert markdown to serialized XHTML or HTML.
post.body = md.convert(post.body)
post.toc = md.toc
return render(request,'blog/detail.html',context={
'post':post,
'comments':comments,
'form':form,
})
右侧导航栏
{# 基模板 #}
详情页添加博客目录
{# blog/detail.html #}
{% block toc %}
文章目录
{{ post.toc | safe }}
{% endblock %}
按类别查找
按标签查找
按时间查找
显示博客目录
分页
Django提供了一个新的类来帮助你管理分页数据,这个类存放在django/core/paginator.py.它可以接收列表、元组或其它可迭代的对象。
def index(request):
all_posts = Post.objects.count()
if all_posts % PER_PAGE != 0:
page_nums = all_posts // PER_PAGE + 1
else:
page_nums = all_posts // PER_PAGE
paginator = Paginator(Post.objects.all(),PER_PAGE)
if request.GET.get('page'):
page = request.GET.get('page')
else:
page = 1
try:
posts = paginator.page(page)
except (PageNotAnInteger,EmptyPage):
posts = paginator.page(1)
posts.has_previous()
posts.has_next()
posts.previous_page_number()
posts.next_page_number()
return render(request, 'blog/index.html',
context={
'title':'博客首页',
'posts':posts,
'pages_num':page_nums,
})
修改主页的html文件有关分页显示的部分
评论列表,共 {{ comments.count }} 条评论
{% for comment in comments %}-
{{ comment.user }}
{{ comment.text }}
{% endfor %}