基于Django构建Blog(07)-Views

业务逻辑将在Views中实现,在Views中会调集相应的ModelsTemplates生成最终的页面提供给用户。

这里所描述的是需要我们自己实现的部分,前面已经提到,内容管理直接使用Django自带的admin site即可,而文章搜索则借助于第三方app:Haystack来实现。

View通常表现为一个简单的函数或类中的某个方法,一个函数致力于完成一项业务,按照前面的设计,系统至少需要实现如下的几个View:

  • 主页(Home):按时间先后给出已发布的文章,最近发布的排在前面
  • 档案(Archives):与Home类似,只是显示方式不同,文章要按照年份进行归类
  • 标签(ArticlesOfTag):给出属于指定Tag的全部文章
  • 分类(ArticlesOfCategory):给出属于指定Category的全部文章
  • 文章(ArticleDetail):给出指定文章的完整内容

每个View对应一个Template,Template的具体实现在下一篇中说明,这里先把各模板文件创建好放在templates目录下,内容为空即可:

  • Home - home.html
  • Archives - archives.html
  • ArticlesOfTag - articles_of_tag.html
  • ArticlesOfCategory - articles_of_category.html
  • ArticleDetail - article_detail.html

apps/blog/views.py文件中实现各View:

 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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from .models import Article
from .models import Category, Tag
from collections import defaultdict
from collections import OrderedDict
from django.views.generic.detail import DetailView
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render, render_to_response, get_object_or_404

def PaginateArticles(articles, per_page, page_num):
    paginator = Paginator(articles, per_page)
    try:
        articles = paginator.page(page_num)
    except PageNotAnInteger:
        articles = paginator.page(1)
    except EmptyPage:
        articles = paginator.page(paginator.num_pages)
    return articles

def Home(req):
    articles = Article.objects.order_by('-create_date')
    articles = PaginateArticles(articles, 6, req.GET.get('page'))
    context = {'articles':articles, 'column':'home'}
    return render_to_response('home.html', context)

def Archives(req):
    articles = Article.objects.order_by('-create_date')
    years = list()
    articles_by_year = defaultdict(list)
    year = articles[0].create_date.year
    years.append(year)
    for article in articles:
        cur_year = article.create_date.year
        articles_by_year[cur_year].append(article)
        if year != cur_year:
            year = cur_year
            years.append(year)
    archives = OrderedDict()
    for year in years:
        archives[year] = articles_by_year[year]
    context = {'archives':archives, 'column':'archives'}
    return render_to_response('archives.html', context)

def ArticlesOfTag(req, slug):
    cur_tag = get_object_or_404(Tag, slug=slug)
    articles = Article.objects.filter(tag=cur_tag).order_by('-create_date')
    articles = PaginateArticles(articles, 6, req.GET.get('page'))
    context = {'articles':articles, 'column':'tag'}
    return render_to_response('articles_of_tag.html', context)

def ArticlesOfCategory(req, slug):
    cur_category = get_object_or_404(Category, slug=slug)
    articles = Article.objects.filter(category
        =cur_category).order_by('-create_date')
    articles = PaginateArticles(articles, 6, req.GET.get('page'))
    context = {'articles':articles, 'column':'category'}
    return render_to_response('articles_of_category.html', context)

class ArticleDetail(DetailView):
    model = Article
    template_name = 'article_detail.html'

Djangodjango/core/paginator.py模块中提供了一些与分页有关的类,基于这些类可以方便的实现文章按页显示,从代码中可以看出,这里的设定是每页显示6篇文章。

另外要注意Home,ArticlesOfTag和ArticlesOfCategory三者的context中给出的文章结果集变量的名字是一样的,都是'articles',这既是有意为之,又是很自然的事情。因为这三者所产生的都是文章的集合,只是基于具体业务要求,集合中的数据不同而已,用相同的变量名很自然;有意为之,是因为这样做的话,可以使这三者对应的模板文件中对文章的处理部分都去使用相同的变量,这就为模板间的extends和include做了准备。


Prev-基于Django构建Blog(06)-Admin
Next-基于Django构建Blog(08)-Templates