1、解决博客标题只显示部分问题
上一节中我们通过Django Haystac实现了博客的搜索功能,但是对于搜索结果并不太满足,因为博客的标题只能显示出部分内容。通过查看源码,我们可以解决这个问题。这部分的源码位于:
虚拟环境目录\Lib\site-packages\haystack\utils\highlighting.py
通过分析该源代码,我们可以看到max_length = 200
为搜索结果显示的最大长度。如果有需要改变的话,可以修改这个数值。我们直接看最后几句代码:
if start_offset > 0:
highlighted_chunk = '...%s' % highlighted_chunk
if end_offset < len(self.text_block):
highlighted_chunk = '%s...' % highlighted_chunk
return highlighted_chunk
这里的start_offset 与end_offset 分别代表高亮代码的开始位置与结束为止,第一个if语句就是为什么标题只显示部分的原因:如果高亮部分在中间的话,前面的部分就直接显示…。理解了这个缘由,我们可以在这之前再加一句判断,如果字符串长度小于max_length 的值的话,我们就直接将其返回就可以了,如下:
if len(self.text_block) < self.max_length:
return self.text_block[:start_offset] + highlighted_chunk
if start_offset > 0:
highlighted_chunk = '...%s' % highlighted_chunk
if end_offset < len(self.text_block):
highlighted_chunk = '%s...' % highlighted_chunk
return highlighted_chunk
如此,即可实现博客标题的全部显示。
但是直接在源码中修改是不方便以后的移植的,关于这块我还不太了解怎么在自己程序中修改源码,除了把源码全部拷进来之外。以后整明白了再过来修改下。
2、实现搜索后结果的分页
haystack在返回搜索结果时,得到的是一个分页page对象,如果我们想要对结果进行分页,可以直接套用这个page对象,但是如果我们想要在search.html页面上添加其它内容的话,还需要对相关的视图函数进行修改。
我们haystack的视图函数位于from haystack.views import SearchView
为此,我们对该视图函数进行重写将就可以了。
view.py
from haystack.views import SearchView
from blog.settings import HAYSTACK_SEARCH_RESULTS_PER_PAGE
class MySearchView(SearchView):
def build_page(self):
#分页重写
super(MySearchView, self).extra_context()
try:
page_no = int(self.request.GET.get('page', 1))
except PageNotAnInteger:
raise HttpResponse("Not a valid number for page.")
if page_no < 1:
raise HttpResponse("Pages should be 1 or greater.")
paginator = Paginator(self.results, HAYSTACK_SEARCH_RESULTS_PER_PAGE, request=self.request)
page = paginator.page(page_no)
return (paginator, page)
然后将之前写的url重写:
urls.py
from myblog.views import MySearchView
url(r'^search/', MySearchView(), name='haystack_search'),
最后,在search.html中添加分页代码:
search.html
<!--分页展示-->
<nav class="pagination">
<div class="pageturn">
<ul class="pagelist">
{% if page.has_previous %}
<li class="long"><a href="?q={{ query }}&page={{ page.previous_page_number }}">上一页</a></li>
{% endif %}
{% for index in page.pages %}
{% if index %}
{% ifequal index page.number %}
<li class="active"><a href="?q={{ query }}&page={{ index }}">{{ index }}</a></li>
{% else %}
<li><a href="?q={{ query }}&page={{ index }}" class="page">{{ index }}</a></li>
{% endifequal %}
{% else %}
<li class="none"><a href="">...</a></li>
{% endif %}
{% endfor %}
{% if page.has_next %}
<li class="long"><a href="?q={{ query }}&page={{ page.next_page_number }}">下一页</a></li>
{% endif %}
</ul>
</div>
</nav>
这里我们用的还是之前主页那里采用的django-pure-pagination。
3、实现分页时序号的连续
我们在对数据进行循环时,如果需要标上序号,可以采用forloop方法,如下所示:
{{ forloop.counter }}
然而,通过这种方法,在点击下一页后,序号还是从1开始,不能接着上一页中的最后一个的序号累加。解决思路如下:
- 获得当前页面的页码,乘以每页展示的对象数目,在加上{{ forloop.counter }}即可
- 当前页面的页码可以通过page.number 获得
- django 中的模板中不能进行加减乘除运算,直接能通过过滤器实现,加法的过滤器是|add ,并没有乘法的过滤器,因此我们需要自定义一个乘法过滤器
- 每个页面展示的对象数目可以在setting.py中定义,然而模板中是不能直接获得该常量的,需要将该常量添加到上下文管理器中
自定义乘法过滤器
原理见官方文档,这里只给出步骤:
首先在myblog项目下,建立一个templatetags的包,里面新建一个py文件,名字任意,我这里取为blog_tags.py:
from django import template
register = template.Library()
@register.filter
def multiply(value, num):
#定义一个乘法过滤器
return (value-1)*num
在模板中,可以这么写:
{% load blog_tags %}
...
{{ page.number|multiply: 5 }}
这里page.number代表当前页面的页码,也就是第几页,对应的是刚才定义的过滤器multiply函数中的value值。 5对应的是函数中的num值。
这样,在其基础上加上forloop.counter即可,如下:
{{ page.number|multiply: 5|add:forloop.counter }}
将setting.py中的常量添加到模板中
上面的代码中显示的每页数目是5,当对其改变的话,还需要将模板中的都改过来,如果页面多的话,改起来很麻烦,不符合程序设计原则。我们可以将值在setting.py中设定,然后添加到上下文管理器中,这样在整个模板中就可以用了。
在你的app目录下建立一个context_processors.py,写入:
from django.conf import settings
def pageNums(request):
return {"HAYSTACK_SEARCH_RESULTS_PER_PAGE": settings.HAYSTACK_SEARCH_RESULTS_PER_PAGE}
然后,再将其在setting.py中的context_processors进行绑定,如下:
TEMPLATES = [
{
...
'OPTIONS': {
...
'blog.context_processors.pageNums',
],
},
},
]
最后,直接在模板中就可以使用该变量HAYSTACK_SEARCH_RESULTS_PER_PAGE
{{ page.number|multiply:HAYSTACK_SEARCH_RESULTS_PER_PAGE|add:forloop.counter }}
如此,即可实现翻页后序号的连续。
——————————————————————————————————————————
项目的完整代码:django_blog
觉得有用的欢迎给个star。