Django 利用管理器实现文章归档

Django管理器:class Manager

       管理器是Django的模型进行数据库查询的接口,Django应用的每个模型都拥有至少一个管理器。默认情况下,Django为每个模型类添加一个名为objects的管理器,然而如果要将objects用于字段名称或想使用其他名称而不是objects来访问管理器,可在每个模型类中重命名他们。自定义的管理器方法可以返回你想要的任何数据,而不需要返回一个查询集。eg: models.py

# 文章模型
class Article(models.Model):
    title = models.CharField(max_length=50, verbose_name='文章标题')
    desc = models.CharField(max_length=50, verbose_name='文章描述')
    content = models.TextField(verbose_name='文章内容')
    click_count = models.IntegerField(default=0, verbose_name='点击次数')
    is_recommend = models.BooleanField(default=False, verbose_name='是否推荐')
    date_publish = models.DateTimeField(auto_now_add=True, verbose_name='发布时间')
    user = models.ForeignKey(User, verbose_name='用户')
    category = models.ForeignKey(Category, blank=True, null=True, verbose_name='分类')
    tag = models.ManyToManyField(Tag, verbose_name='标签')
    objects = ArticleManager()  # 在模型中使用自定义的管理器

要实现文章归档,需要根据日期对文章这个模型类进行筛选:我们的目的是根据 ‘年-月’来归并所有文章,此外若 17年8月没有文章,则归档也不显示17年8月这一空白归档。类似如下:

            

为实现根据年-月的文章筛选,可以早models.py中建立一个文章管理器,继承自models.Manager:

class ArticleManager(models.Manager):
    def distinct_date(self):  # 该管理器定义了一个distinct_date方法,目的是找出所有的不同日期
        distinct_date_list = []  # 建立一个列表用来存放不同的日期 年-月
        date_list = self.values('date_publish')  # 根据文章字段date_publish找出所有文章的发布时间
        for date in date_list:  # 对所有日期进行遍历,当然这里会有许多日期是重复的,目的就是找出多少种日期
            date = date['date_publish'].strftime('%Y/%m 存档') # 取出一个日期改格式为 ‘xxx年/xxx月 存档’
            if date not in distinct_date_list:
                distinct_date_list.append(date)
        return distinct_date_list

上文代码建立的管理器需要在文章模型类加上语句:objects = ArticleManager()  ,然后就可以调用 distinct_date 方法了: archive_list = Article.objects.distinct_date(),对比:

article_list = Article.objects.all() # 获取所有文章,获取到的是所有文章对象的一个列表

archive_list = Article.objects.distinct_date() # 文章归档 获取到的列表格式为: xxx年/xxx月 存档

我们要将 archive_list 这个列表显示在html页面中,所有需要一个for循环:在base.html中加入:

<div class="tuwen">
      <h3>文章归档</h3>
      <ul>
        {% for archive in archive_list %}
        <li>
          <p><span class="tutime font-size-18"><a href='{% url 'archive' %}?year={{ archive | slice:":4" }}&month={{ archive | slice:"5:7" }}'>{{ archive }}</a></span></p>
        </li>
        {% endfor %}
      </ul>
    </div>

 

 

 左图即为html中的结果。  这里 {% url %} 这个模板标签的作用是解析视图函数对应的 URL 模式, 那么上文代码中 ‘{% url 'archive' %}’ 是指解析views.py 中视图函数archive对应的url模式。那么,每行归档文字都有了一个链接,格式为: http://127.0.0.1:8000/archive/?year=2015&month=02,{% url %}解析时会将year=2015和month=02 这两个参数值传递到 views.py 请求中。 综上,至此我们只实现了在base主页面上显示左图,并且为各个归档赋予了链接,下一步我们需要为这个链接编写相应的操作。

 

 

 

 

编写urls.py 和 views.py

回顾上文的链接http://127.0.0.1:8000/archive/?year=2015&month=02, 我们看到链接为 archive, 所以需要对应的urls 和 视图函数:

urls.py:
from
blog.views import index, archive urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^$', index, name='index'), url(r'^archive/$', archive, name='archive'), # url路由,那么http://127.0.0.1:8000/archive/ 实现了,后面的参数咋办?别急,在views中取出这个请求的参数 ]
views.py:
def
archive(request):
    year = request.GET.get('year', None)
    month = request.GET.get('month', None)   # 取出两个参数 year,month

    article_list = Article.objects.filter(date_publish__icontains=year+'-'+month) # 根据参数year,month进行过滤, 记得字段名+__icontains表大小写不敏感的包含匹配

    return render(request, 'archive.html', locals())

至此,我们将所有 http://127.0.0.1:8000/archive/?year=XXX&month=XX 都实现url解析,并筛选出来满足year=XXX,month=XX的文章,下面我们需要在 archive.html 中将这些文章显示出来。

 

 

归档页面archive.html

在archive.html中加入文章归档显示内容

    <div class="topnews">
      <h2>文章归档</h2>
      {% for article in article_list %}  # 将XXX年XX月的所有文章进行展示
      <div class="blogs">
        <ul>
          <h3><a href="/">{{ article.title }}</a></h3>
          <p>{{ article.desc }}...</p>
          <p class="autor"><span class="lm f_l">{% for tag in article.tag.all %}<a href="/">{{ tag.name }}</a>&nbsp;</span>{% endfor %}<span class="dtime f_l">{{ article.date_publish | date:'Y-m-d' }}</span><span class="viewnum f_r">浏览(<a href="/">{{ article.click_count }}</a></span><span class="pingl f_r">评论(<a href="/">{{ article.comment_set.all.count }}</a></span></p>
        </ul>
      </div>
      {% endfor %}
    </div>
注:下面也有分页代码

final:

 

注:另一种直接在views.archive中直接进行时间排序处理的方法,没有利用管理器,较为简洁。传送门

 

posted @ 2017-08-10 13:26  三年一梦  阅读(1764)  评论(0编辑  收藏  举报