上一篇‘博客系統’的博客尚未實現評論,按標籤搜索、按日期搜索、按分類搜索的功能,這篇博客主要是對以上功能的增長。html
第一步:新建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')), ]
第二步:編寫評論的數據庫表單django
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.pymarkdown
# 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<id>\d+)/$',views.post_comment,name='post_comment'), ]
第四步:編寫評論表單app
# 同步與數據庫評論的形式 from comments.models import Comment class CommentForm(forms.ModelForm): class Meta: model = Comment fields = ['user','email','text']
第五步:修改HTML文件中關於評論的部分ide
<section class="comment-area" id="comment-area"> <hr> <h3>發表評論</h3> <form action="{% url 'comment:post_comment' post.id %}" method="post" class="comment-form"> {% csrf_token %} <div class="row"> <div class="col-md-4"> <label for="{{ form.user.id }}">{{ form.user.label }}</label> {{ form.user }} </div> <div class="col-md-4"> <label for="{{ form.email.id }}">{{ form.email.label }}</label> {{ form.email }} </div> <div class="col-md-12"> <label for="{{ form.text.id }}">{{ form.text.label }}</label> {{ form.text }} <button type="submit" class="comment-btn">發表</button> </div> </div> <!-- row --> </form> <div class="comment-list-panel"> <h3>評論列表,共 <span>{{ comments.count }}</span> 條評論</h3> <ul class="comment-list list-unstyled"> {% for comment in comments %} <li class="comment-item"> <span class="nickname">{{ comment.user }}</span> <time class="submit-date" datetime="{{ comment.create_time }}">{{ comment.create_time }}</time> <div class="text"> {{ comment.text }} </div> </li> {% endfor %} </ul> </div> </section>
實現按標籤搜索、按日期搜索、按分類搜索的功能函數
第一步:自定義標籤post
在某個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'))
第二步: 編寫標籤查找的路由和視圖函數url
路由spa
#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<id>\d+)/$', views.detail, name='detail'), url(r'^archive/(?P<year>\d{4})/(?P<month>\d{1,2})/', views.archive, name='archive'), url(r'^category/(?P<id>\d+)/', views.category, name='category'), url(r'^tag/(?P<id>\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, })
右側導航欄
{# 基模板 #} <aside class="col-md-4"> {% block toc %} {% endblock %} <div class="widget widget-recent-posts"> <h3 class="widget-title">最新文章</h3> <ul> {% get_recent_posts as recent_posts %} {% for post in recent_posts %} <li> <a href="{{ post.get_url }}">{{ post.title }}</a> </li> {% endfor %} </ul> </div> <div class="widget widget-archives"> <h3 class="widget-title">歸檔</h3> <ul> {% archives as dates %} {% for date in dates %} <li> <a href="{% url 'blog:archive' date.year date.month %}">{{ date.year }}年 {{ date.month }}月</a> </li> {% endfor %} </ul> </div> <div class="widget widget-category"> <h3 class="widget-title">分類</h3> <ul> {% get_category as categories %} {% for category in categories %} <li> <a href="{% url 'blog:category' category.id %}">{{ category.name }}<span class="post-count">({{ category.num_posts }})</span></a> </li> {% endfor %} </ul> </div> <div class="widget widget-tag-cloud"> <h3 class="widget-title">標籤雲</h3> <ul> {% get_tags as tags %} {% for tag in tags %} <li> <a href="{% url 'blog:tag' tag.id %}">{{ tag.name }}</a> </li> {% endfor %} </ul> </div>
詳情頁添加博客目錄
{# blog/detail.html #} {% block toc %} <div><h3 class="widget-title">文章目錄</h3> {{ post.toc | safe }} </div> {% 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文件有關分頁顯示的部分
<div class="pager"> {% if posts.has_previous %} <a href="?page={{ posts.previous_page_number }}">上一頁</a> {% else %} <a href="#">上一頁</a> {% endif %} <span class="current">第 {{ posts.number }} 頁 / 共 {{ pages_num }} 頁</span> {% if posts.has_next %} <a href="?page={{ posts.next_page_number }}">下一頁</a> {% else %} <a href="#">下一頁</a>