1. 前后博文

1.1 filter筛选条件

·Articles.objects.filter(article_type?)

等于:直接筛选 大于:gt (greather than) 大于等于:gte 小于:lt (less than) 小于等于:lte 包含:(加i忽略大小写)contains 开头是:startswith 结尾是:endswith 其中之一:in 范围:range 日期:year __month

  1. >>> from s2aclab.models import Articles
  2. >>> Articles.objects.filter(title__contains='django')
  3. <QuerySet []>
  4. >>> Articles.objects.filter(title__contains='code')
  5. <QuerySet [<Articles: <Article:第一篇code>>]>
  6. >>> Articles.objects.filter(title__icontains='cOde')
  7. <QuerySet [<Articles: <Article:第一篇code>>]>
  8. >>> Articles.objects.filter(id__in=[1,3,4,6])
  9. <QuerySet [<Articles: <Article:for 3>>, <Articles: <Article:for 1>>, <Articles: <Article:for 2>>, <Articles: <Article:第一篇research>>]>
  10. >>>

修改article_details.html 和views中的类

def article_details(request, art_pk):
    context = {}
    article = get_object_or_404(Articles, pk=art_pk)
    context['article'] = article
    context['next_article'] = Articles.objects.filter(created_time__gt=article.created_time).last()  # .last()表示取最后一条
    context['previous_article'] = Articles.objects.filter(
        created_time__lt=article.created_time).first()    # .first()表示取第一条
    return render(request, 'article_details.html', context)
<!-- 前后翻页 -->
<nav aria-label="...">
    <ul class="pager">
        {%if previous_article %}
        <li class="previous"><a href="{% url 'article_details' previous_article.pk %}"><span
                aria-hidden="true">&larr;</span>Previous</a></li>
        {% else %}

        {% endif %}
        {% if next_article %}
        <li class="next"><a href="{% url 'article_details' next_article.pk %}">Next <span
                aria-hidden="true">&rarr;</span></a></li>
        {% else %}

        {% endif %}
    </ul>
</nav>

2 博文分类

2.1 条件中的双下划线

字段查询类型 外键扩展(以博客分类为例) 日期拓展(以月份分类为例) 支持链式查询:可以一直链接下去

>>> Articles.objects.filter(created_time__month=5)
<QuerySet [<Articles: <Article:第一篇code>>, <Articles: <Article:第一篇research>>]>

dates()

  • datesfieldkindorder =’ASC’

返回一个QuerySet,其结果是一个datetime.date 对象列表,该对象列表表示的内容中特定种类的所有可用日期QuerySet

field应该是DateField您的模型的名称。 kind应该是"year""month""day"datetime.date结果列表中的每个 对象都将“截断”到给定 type

  • "year" 返回该字段的所有不同年份值的列表。
  • "month" 返回该字段的所有不同年份/月份值的列表。
  • "day" 返回该字段的所有不同年/月/日值的列表。

order(默认为'ASC')应为'ASC''DESC'。这指定了如何订购结果。

例子:

>>> Entry.objects.dates('pub_date', 'year')
[datetime.date(2005, 1, 1)]
>>> Entry.objects.dates('pub_date', 'month')
[datetime.date(2005, 2, 1), datetime.date(2005, 3, 1)]
>>> Entry.objects.dates('pub_date', 'day')
[datetime.date(2005, 2, 20), datetime.date(2005, 3, 20)]
>>> Entry.objects.dates('pub_date', 'day', order='DESC')
[datetime.date(2005, 3, 20), datetime.date(2005, 2, 20)]
>>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day')
[datetime.date(2005, 3, 20)]

在views.py中的articles_list()中添加

    context['article_dates'] = Articles.objects.dates('created_time','month',order='DESC')

articles_list.html中添加日期分类框

<!-- date categories -->
<div class="panel panel-default">
    <div class="panel-heading">Date Categories</div>
    <div class="panel-body">
        <ul class="article_date">
            {% for article_date in article_dates %}
            <li>
                <a href="{% url 'article_with_date' article_date.year article_date.month %}">
                    {{ article_date| date:"Y-m" }}
                </a>
            </li>
            {% empty %}
            <li></li>
            {% endfor %}
        </ul>
    </div>
</div>
<!-- END date categories -->

新建artilce_with_date.html

<!-- coding=utf8 -->
{% extends 'articles_list.html' %}
<!--title -->
{% load static%}
{% block title %}
{{article_type.type_name}}
{% endblock %}
{% block article_list_title %}
    {{ article_with_date }} | {{ page_of_articles.paginator.count }} Blogs <a href="{% url 'articles_list' %}"></a>
{% endblock %}

新建article_with_date()

def article_with_date(request, year, month):

    articles_all_list = Articles.objects.filter(created_time__year=year, created_time__month=month)

    context = get_all_common_data(request,articles_all_list)

    context['article_with_date'] = '%s-%s'%(year,month)
    return render(request, 'article_with_date.html', context)

articles_list() article_with_type() 以及 article_with_date()中公共的数据部分取出新建get_all_common_data()函数,简化代码

def get_all_common_data(request,articles_all_list):
    paginator = Paginator(
        articles_all_list, settings.ARTICLE_NUMBER_EACH_PAGE)  # 4篇一页
    # 获取页码参数(GET请求)  .GET 字典 使用get方法判断是否有page值,没有返回1
    page_num = request.GET.get("page", 1)
    # 输入许可字符范围外的字符会返回1
    page_of_articles = paginator.get_page(page_num)

    # 获取当前页
    current_page = page_of_articles.number
    # 页码显示范围
    page_range = [i for i in range(
        current_page-2, current_page+3) if 0 < i <= paginator.num_pages]
    # 第一页
    if page_range[0] >= 2:
        page_range.insert(0, 1)  # 第一位插入1页码
        if page_range[1] != 2:
            page_range.insert(1, '...')   # 加上...
    # 最后一页
    if page_range[-1] <= paginator.num_pages - 1:
        if page_range[-1] != paginator.num_pages - 1:
            page_range.append('...')      # 加上...
        page_range.append(paginator.num_pages)

    context = {}
    # context['articles'] = page_of_articles.object_list  #   前端页面
    context['page_of_articles'] = page_of_articles  # 当前页码
    context['article_types'] = ArticleType.objects.all()
    context['article_dates'] = Articles.objects.dates('created_time', 'month', order='DESC')
    context['page_range'] = page_range
    return context

2.2 博文分类统计

获取对应分类的博文数量 python 直接查询

新建get_categories_count()

类对象article_type(ArticleType)添加属性.article_count

新建字典article_dates_dict = dict()

#   获取对应的分类与博文数 

def get_all_common_data(request,articles_all_list):
    ...
    context['article_types'] = ArticleType.objects.annotate(article_count=Count('art_art'))  # 所有分类
    context['article_dates'] = get_categories_count()   #   日期分类与数量

def get_categories_count():
    '''
    # 获取对应分类的博文数量 简单粗暴方法 占服务器
    article_types = ArticleType.objects.all()
    artcile_types_list = []
    for article_type in article_types:
            #   类对象`article_type(ArticleType)`添加属性`.article_count`
        article_type.article_count = Articles.objects.filter(
            article_type=article_type).count()
        artcile_types_list.append(article_type)

    # 获取对应分类的博文数量 annotate
    # ArticleType.objects.annotate(article_count=Count('art_art'))    # 返回sql语句
    '''

    # 获取对应日期的博文数量
    article_dates = Articles.objects.dates('created_time', 'month', order = 'DESC')
    article_dates_dict = dict()
    for date in article_dates:
        article_dates_dict[date] = Articles.objects.filter(created_time__year=date.year,
                                                            created_time__month=date.month).count()

    return article_dates_dict

articles_list.html

<ul class="article_type">
    {% for type in article_types %}
    <li>
        <a href="{% url 'article_with_type' type.pk %}">
            {{ type.type_name }} ({{type.article_count}})
        </a>
    </li>
    {% empty %}
    <li></li>
    {% endfor %}
</ul>

<ul class="article_date">
    {% for article_date,article_count in article_dates.items %}
    <li>
        <a href="{% url 'article_with_date' article_date.year article_date.month %}">
            {{ article_date| date:"Y-m" }} ({{article_count}})
        </a>
    </li>
    {% empty %}
    <li></li>
    {% endfor %}
</ul>

14 博文翻页以及按月分类 - 图1

annotate注释——拓展查询字段

views.py get_all_common_data()

# 返回sql语句
context['article_types'] = ArticleType.objects.annotate(article_count=Count('art_art'))  # 所有分类

需要在models.py中修改

class Articles(models.Model):
    article_type = models.ForeignKey(ArticleType,on_delete=models.DO_NOTHING,related_name='art_art')