Django 搜索和Readmore与RSS和分页
搜索和ReadMore 搜索功能 搜索功能的实现设计:
前端界面输入搜索关键字, 传送到对应view中
在对应的view中进行数据库关键字搜索
这里搜索可以只对文章名搜索或者全文搜索,首先在my_blog/templates下添加所有输入框,在base.html中,对侧边栏的代码进行如下的修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <div class="sidebar pure-u-1 pure-u-md-1-4"> <div class="header"> <h1 class="brand-title"><a href="{% url "home" %}">Andrew Liu Blog</a></h1> <h2 class="brand-tagline">Snow Memory</h2> <nav class="nav"> <ul class="nav-list"> <li class="nav-item"> <a class="button-success pure-button" href="/">Home</a> </li> <li class="nav-item"> <a class="button-success pure-button" href="{% url "archives" %}">Archives</a> </li> <li class="nav-item"> <a class="pure-button" href="https://github.com/Andrew-liu/my_blog_tutorial">Github</a> </li> <li class="nav-item"> <a class="button-error pure-button" href="http://weibo.com/dinosaurliu">Weibo</a> </li> <li class="nav-item"> <a class="button-success pure-button" href="/">Pages</a> </li> <li class="nav-item"> <a class="button-success pure-button" href="{% url "about_me" %}">About Me</a> </li> <li> <form class="pure-form" action="/search/" method="get"> <input class="pure-input-3-3" type="text" name="s" placeholder="search"> </form> </li> </ul> </nav> </div> </div>
在my_blog/article/views.py中添加查询逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def blog_search(request): if 's' in request.GET: s = request.GET['s'] if not s: return render(request,'home.html') else: post_list = Article.objects.filter(title__icontains = s) if len(post_list) == 0 : return render(request,'archives.html', {'post_list' : post_list, 'error' : True}) else : return render(request,'archives.html', {'post_list' : post_list, 'error' : False}) return redirect('/')
这里为了简单起见, 直接对archives.html进行修改, 使其符合查询逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 {% extends "base.html" %} {% block content %} <div class="posts"> {% if error %} <h2 class="post-title">NOT Found</a></h2> {% else %} {% for post in post_list %} <section class="post"> <header class="post-header"> <h2 class="post-title"><a href="{% url "detail" id=post.id %}">{{ post.title }}</a></h2> <p class="post-meta"> Time: <a class="post-author" href="#">{{ post.date_time |date:"Y /m /d"}}</a> <a class="post-category post-category-js" href="{% url "search_tag" tag=post.category %}">{{ post.category }}</a> </p> </header> </section> {% endfor %} {% endif %} </div><!-- /.blog-post --> {% endblock %}
添加了if判断逻辑, 然后还需要修改views中的archives
1 2 3 4 5 6 7 def archives(request) : try: post_list = Article.objects.all() except Article.DoesNotExist : raise Http404 return render(request, 'archives.html', {'post_list' : post_list, 'error' : False})
最后添加my_blog/my_blog/urls.py设置url
1 2 3 4 5 6 7 8 9 10 11 12 13 urlpatterns = [ # Examples: # url(r'^$', 'my_blog.views.home', name='home'), # url(r'^blog/', include('blog.urls')), url(r'^admin/', include(admin.site.urls)), url(r'^$', views.home, name = 'home'), url(r'^(?P<id>\d+)/$', views.detail, name='detail'), url(r'^archives/$', views.archives, name = 'archives'), url(r'^aboutme/$', views.about_me, name = 'about_me'), url(r'^tag(?P<tag>\w+)/$', views.search_tag, name = 'search_tag'), url(r'^search/$',views.blog_search, name = 'search'), ]
最终效果。
ReadMore功能 对于ReadMore的前段按钮界面设置早已经添加过了, 所以这里只需要进行简单的设置就好了
通过使用Django中内建的filter就可以速度实现
1 2 {{ value|truncatewords:2 }} #这里2表示要显示的单词数, 以后的会被截断, 不在显示 这里只需要修改my_blog/templates/home.html界面中的变量的过滤器
1 2 #将正文截断设置为10 {{ post.content|custom_markdown|truncatewords_html:20 }}
在浏览器中输入http://localhost:9000/可以看到效果(最好把博文设置的长一些)
Django是一个全面型框架, 很多功能都可以直接找到, 对于RSS功能, 可以从其中的高层框架的聚合Feed框架中找到(The syndication feed framework)
上层Feed生成框架可以直接应用Feed类, 我们可以直接继承Feed在其中定义自己的方法
在my_blog/article/views.py中定义类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from django.contrib.syndication.views import Feed #注意加入import语句 class RSSFeed(Feed) : title = "RSS feed - article" link = "feeds/posts/" description = "RSS feed - blog posts" def items(self): return Article.objects.order_by('-date_time') def item_title(self, item): return item.title def item_pubdate(self, item): return item.date_time def item_description(self, item): return item.content
然后在my_blog/article/models.py中重写get_absolute_url方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from django.db import models from django.core.urlresolvers import reverse # Create your models here. class Article(models.Model) : title = models.CharField(max_length = 100) #博客题目 category = models.CharField(max_length = 50, blank = True) #博客标签 date_time = models.DateTimeField(auto_now_add = True) #博客日期 content = models.TextField(blank = True, null = True) #博客文章正文 #获取URL并转换成url的表示格式 def get_absolute_url(self): path = reverse('detail', kwargs={'id':self.id}) return "http://127.0.0.1:8000%s" % path def __str__(self) : return self.title class Meta: ordering = ['-date_time']
之后在my_blog/my_blog/urls.py中设置对应的url
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from django.conf.urls import url from django.contrib import admin from article import views from article.views import RSSFeed urlpatterns = [ # Examples: # url(r'^$', 'my_blog.views.home', name='home'), # url(r'^blog/', include('blog.urls')), url(r'^admin/', admin.site.urls), url(r'^$', views.home', name = 'home'), url(r'^(?P<id>\d+)/$', views.detail', name='detail'), url(r'^archives/$', views.archives', name = 'archives'), url(r'^aboutme/$', views.about_me', name = 'about_me'), url(r'^tag(?P<tag>\w+)/$', views.search_tag', name = 'search_tag'), url(r'^search/$',views.blog_search', name = 'search'), url(r'^feed/$', RSSFeed(), name = "RSS"), #新添加的urlconf, 并将name设置为RSS, 方便在模板中使用url ]
下面修改my_blog/templates/base.html, 在其中添加RSS按钮
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="A layout example that shows off a blog page with a list of posts."> <title>{% block title %} Andrew Liu Blog {% endblock %}</title> <link rel="stylesheet" href="http://labfile.oss.aliyuncs.com/courses/487/pure-min.css"> <link rel="stylesheet" href="http://labfile.oss.aliyuncs.com/courses/487/grids-responsive-min.css"> <link rel="stylesheet" href="http://labfile.oss.aliyuncs.com/courses/487/blog.css"> <link rel="stylesheet" href="http://picturebag.qiniudn.com/monokai.css"> </head> <body> <div id="layout" class="pure-g"> <div class="sidebar pure-u-1 pure-u-md-1-4"> <div class="header"> <h1 class="brand-title"><a href="{% url "home" %}">Andrew Liu Blog</a></h1> <h2 class="brand-tagline">Snow Memory</h2> <nav class="nav"> <ul class="nav-list"> <li class="nav-item"> <a class="button-success pure-button" href="/">Home</a> </li> <li class="nav-item"> <a class="button-success pure-button" href="{% url "archives" %}">Archives/a> </li> <li class="nav-item"> <a class="pure-button" href="https://github.com/Andrew-liu/my_blog_tutorial">Github</a> </li> <li class="nav-item"> <a class="button-error pure-button" href="http://weibo.com/dinosaurliu">Weibo</a> </li> <li class="nav-item"> <a class="button-success pure-button" href="/">Pages</a> </li> <li> <form class="pure-form" action="/search/" method="get"> <input class="pure-input-3-3" type="text" name="s" placeholder="search"> </form> </li> <li class="nav-item"> <a class="button-success pure-button" href="{% url "about_me" %}">About Me</a> </li> <li class="nav-item"> <a class="button-success pure-button" href="{% url "RSS" %}">RSS</a> </li> </ul> </nav> </div> </div> <div class="content pure-u-1 pure-u-md-3-4"> <div> {% block content %} {% endblock %} <div class="footer"> <div class="pure-menu pure-menu-horizontal pure-menu-open"> <ul> <li><a href="http://andrewliu.tk/about/">About Me</a></li> <li><a href="http://twitter.com/yuilibrary/">Twitter</a></li> <li><a href="http://github.com/yahoo/pure/">GitHub</a></li> </ul> </div> </div> </div> </div> </div> </body> </html>
保存后, 在浏览器中输入http://localhost:9000/可以看到新增的RSS按钮 , 点击看以看到对应的效果。
更多功能可以查看The syndication feed framework官方文档
分页功能 当博客文章较多的时候, 我们并不希望以此在主页上显示全部的博客文章, 而是希望能够每页显示固定的文章数目, 这样既能提高性能, 也能提高美观度, 何乐而不为呢?
现在这一章节来看看怎么实现分页功能
修改my_blog/article/views.py中的home函数
1 2 3 4 5 6 7 8 9 10 11 12 13 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger #添加包 def home(request): posts = Article.objects.all() #获取全部的Article对象 paginator = Paginator(posts, 2) #每页显示两个 page = request.GET.get('page') try : post_list = paginator.page(page) except PageNotAnInteger : post_list = paginator.page(1) except EmptyPage : post_list = paginator.paginator(paginator.num_pages) return render(request, 'home.html', {'post_list' : post_list})
修改my_blog/templates下的home.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 {% extends "base.html" %} {% load custom_markdown %} {% block content %} <div class="posts"> {% for post in post_list %} <section class="post"> <header class="post-header"> <h2 class="post-title"><a href="{% url "detail" id=post.id %}">{{ post.title }}</a></h2> <p class="post-meta"> Time: <a class="post-author" href="#">{{ post.date_time |date:"Y M d"}}</a> <a class="post-category post-category-js" href="{% url "search_tag" tag=post.category %}">{{ post.category|title }}</a> </p> </header> <div class="post-description"> <p> {{ post.content|custom_markdown|truncatewords:10 }} </p> </div> <a class="pure-button" href="{% url "detail" id=post.id %}">Read More >>> </a> </section> {% endfor %} {% if post_list.object_list and post_list.paginator.num_pages > 1 %} <div> <ul class="pager"> {% if post_list.has_previous %} <li><a href="?page={{ post_list.previous_page_number }}">Pre Page</a></li> {% endif %} {% if post_list.has_next %} <li><a href="?page={{ post_list.next_page_number }}">Next Page</a></li> {% endif %} </ul> </div> {% endif %} </div><!-- /.blog-post --> {% endblock %}
我设置的是每页显示两篇博文, 可以修改成其他数值
更多细节可以查看pagination官方文档
保存后, 在浏览器中输入http://localhost:9000/可以看到新增的下一页按钮(博客文章要多加几篇) , 点击看以看到对应的效果
到目前为止, 博客的基本功能都实现了, 下一篇我们将讲到怎么在云端进行部署
最后我们把整个blog更新到github仓库中
1 2 3 4 5 $ git add . #添加全部更新到暂存区 $ git commit -m "rss and paginator" #提交到git [master b53356b] rss and paginator 2 files changed, 24 insertions(+), 1 deletion(-) $ git push #提交到github中