技术交流QQ群:1027579432,欢迎你的加入!

本教程来源于B站杨仕航Django2.0开发视频教程,如需转载,必须注明来源!

1.上一篇博客和下一篇博客

  • 对比当前博客,得到上一篇或下一篇博客

2.filter筛选条件

filter筛选条件.png

  • 打开blog文件目录下的views.py文件,修改当中的blog_detail()函数,具体内容如下:
      def blog_detail(request, blog_pk):
          context = {}
          blog = get_object_or_404(Blog, pk=blog_pk)
          context['previous_blog'] = Blog.objects.filter(
              created_time__gt=blog.created_time).last()
          context['next_blog'] = Blog.objects.filter(
              created_time__lt=blog.created_time).first()
          context['blog'] = blog
          return render_to_response('blog/blog_detail.html', context)
  • 接着修改template文件目录下的blog_detail.html模板文件,修改其内容增加一个类名为blog-more的div盒子后,如下所示:
      <div class="blog-more">
          <p>上一篇:{{ previous_blog.title }}</p>
          <p>下一篇: {{ next_blog.title }}</p>
      </div>
    效果.png
    存在的问题.png
  • 接着修改template文件目录下的blog_detail.html模板文件,修改其内容增加if判断条件,从而解决上述存在的问题。如下所示:
      <div class="blog-more">
          <p>上一篇:
              {% if previous_blog %}
                 <a href="{% url 'blog_detail' previous_blog.pk %}">{{ previous_blog.title }}</a>
              {% else %}
                  没有了
              {% endif %}
          </p>
          <p>下一篇:
              {% if next_blog %}
                 <a href="{% url 'blog_detail' next_blog.pk %}">{{ next_blog.title }}</a>
              {% else %}
                  没有了
              {% endif %}
          </p>
      </div>
    效果.png
  • 然后修改类名为blog-more的div盒子的CSS样式,打开blog.css文件,增加如下内容:
      div.blog-more {
          margin-top: 1em;
      }
  • shell模式下演示其他filter筛选条件
      >>> from blog.models import Blog
      >>> Blog.objects.filter(title__contains="Django")
      <QuerySet [<Blog: <Blog: Django简介>>]>
      >>> Blog.objects.filter(title__icontains="django")
      <QuerySet [<Blog: <Blog: Django简介>>]>
      >>> Blog.objects.filter(id__in=[1, 3, 4])
      <QuerySet [<Blog: <Blog: 人物介绍>>, <Blog: <Blog: 长内容的博客>>]>
      >>> Blog.objects.filter(id__range=(1,4))
      <QuerySet [<Blog: <Blog: 人物介绍>>, <Blog: <Blog: 长内容的博客>>]>
      >>> Blog.objects.filter(id__range=(3,6))
      <QuerySet [<Blog: <Blog: shell模式下的第一篇博客>>, <Blog: <Blog: Django简介>>, <Blog: <Bl
      og: 人物介绍>>, <Blog: <Blog: 长内容的博客>>]>

3.exclude排除条件

exclude排除条件.png

  • exclude排除条件的具体用法如下所示:
      >>> Blog.objects.exclude(pk=3)
      <QuerySet [<Blog: <Blog: for 30>>, <Blog: <Blog: for 29>>, <Blog: <Blog: for 28>>, <Blog: <Blog: for 27>>, <Blog: <Blog: for 26>>, <Blog: <Blog: for 25>>, <Blog: <Blog: for 24>>, <Blog: <Blog: for 23>>, <Blog: <Blog: for 22>>, <Blog: <Blog: for 21>>, <Blog: <Blog: for 20>>, <Blog: <Blog: for 19>>, <Blog: <Blog: for 18>>, <Blog: <Blog: for 17>>, <Blog: <Blog: for 16>>, <Blog: <Blog: for 15>>, <Blog: <Blog: for 14>>, <Blog: <Blog: for 13>>, <Blog: <Blog: for 12>>, <Blog: <Blog: for 11>>, '...(remaining elements truncated)...']>

4.条件中的双下划线

条件中的双下划线.png

  • 条件中的双下划线的具体用法如下所示:
    >>> Blog.objects.filter(created_time__year=2020)
    <QuerySet [<Blog: <Blog: for 30>>, <Blog: <Blog: for 29>>, <Blog: <Blog: for 28>>, <Blog: <Blog: for 27>>, <Blog: <Blog: for 26>>, <Blog: <Blog: for 25>>, <Blog: <Blog: for 24>>, <Blog: <Blog: for 23>>, <Blog: <Blog: for 22>>, <Blog: <Blog: for 21>>, <Blog: <Blog: for 20>>, <Blog: <Blog: for 19>>, <Blog: <Blog: for 18>>, <Blog: <Blog: for 17>>, <Blog: <Blog: for 16>>, <Blog: <Blog: for 15>>, <Blog: <Blog: for 14>>, <Blog: <Blog: for 13>>, <Blog: <Blog: for 12>>, <Blog: <Blog: for 11>>, '...(remaining elements truncated)...']>

5.按月分类

  • 打开blog文件目录下的urls.py文件,添加按月分类的路由地址。如下所示:
      from django.urls import path
      from . import views
    
    
urlpatterns = [
    # http:localhost:8000/blog/1
    path('', views.blog_list, name="blog_list"),
    path('<int:blog_pk>', views.blog_detail, name="blog_detail"),
    path('type/<int:blog_type_pk>', views.blogs_with_type, name="blogs_with_type"),
    path('date/<int:year>/<int:month>',
         views.blogs_with_date, name="blogs_with_date"),
]
```
  • 然后打开blog文件目录下的views.py文件,在blog_list()方法中增加产生按月分类的字段context['blog_dates']。如下所示:

      context['blog_dates'] = Blog.objects.dates("created_time", "month", order="DESC")
  • 因为按月分类的前端页面与博客列表的前端页面整体相似,只需要在博客列表页面中增加按月分类的显示即可。因此修改博客列表页面的模板文件blog_list.html,如下所示:

       <div class="panel panel-default">
          <div class="panel-heading">
              日期归档
          </div>
          <div class="panel-body">
              <ul>
                  {% for blog_date in blog_dates %}
                      <li>{{ blog_date|date:"Y年m月"}}</li>
                  {% endfor %}
              </ul>
          </div>
      </div>
  • 在全局static文件夹中的base.css中增加如下代码,则可以删除li前面的小黑点。

      * {
          list-style: none;
      }
  • 接着给按月分类增加超链接,修改博客列表页面的模板文件blog_list.html,给{{ blog_date|date:"Y年m月"}}增加一个超链接。如下所示:

      <div class="panel panel-default">
          <div class="panel-heading">
              日期归档
          </div>
          <div class="panel-body">
              <ul>
                  {% for blog_date in blog_dates %}
                      <li>
                          <a href="{% url 'blogs_with_date' blog_date.year blog_date.month %}">                                    {{ blog_date|date:"Y年m月" }}
                          </a>
                      </li>
                  {% endfor %}
              </ul>
          </div>
      </div>
  • 接着,打开blog文件目录下的views.py文件,当中增加blogs_with_date()方法,如下所示:

      def blogs_with_date(request, year, month):
          blogs_all_list = Blog.objects.filter(
              created_time__year=year, created_time__month=month)
    
          paginator = Paginator(blogs_all_list, settings.EACH_PAGE_BLOGS_NUMBER)
          page_num = request.GET.get('page', 1)  # 获取url的页码参数(GET请求)
          page_of_blogs = paginator.get_page(page_num)
          current_page_num = page_of_blogs.number  # 获取当前页码
          # 获取当前页码前后各两页的页码范围
          page_range = list(range(max(current_page_num - 2, 1), current_page_num)) + \
              list(range(current_page_num, min(
                  current_page_num + 2, paginator.num_pages) + 1))
          # 加上省略页码标记
          if page_range[0] - 1 >= 2:
              page_range.insert(0, '...')
          if paginator.num_pages - page_range[-1] >= 2:
              page_range.append('...')
    
          # 加上首页和尾页
          if page_range[0] != 1:
              page_range.insert(0, 1)
          if page_range[-1] != paginator.num_pages:
              page_range.append(paginator.num_pages)
    
          context = {}
          context['blogs_with_date'] = "%s年%s月" % (year, month)
          context['blogs'] = page_of_blogs.object_list
          context['page_of_blogs'] = page_of_blogs
          context['page_range'] = page_range
          context['blog_types'] = BlogType.objects.all()
          context['blog_dates'] = Blog.objects.dates(
              "created_time", "month", order="DESC")
          return render_to_response('blog/blogs_with_date.html', context)
  • 最后,在templates目录下的,blog目录下创建blog_with_date.html模板文件,内容如下所示。这样,点击博客里面中的具体按月分类的年和月就能检索出符合当前年月的博客。
    如下所示:

      {% extends 'blog/blog_list.html' %}
      {# blogs_with_date.html文件内容 #}
    
      {# 页面标题 #}
      {% block title %}
          {{ blogs_with_date }}
      {% endblock %}
    
      {% block blog_list_title %}
          日期归档:{{ blogs_with_date }}
          <a href="{% url 'blog_list' %}">查看全部博客</a>
      {% endblock %}

    6.重构views.py中的处理方法

  • 由于blog文件目录下的view.py文件中的方法blog_list()、blogs_with_type()、blogs_with_date()中含有大量重复的代码,因此需要进行代码重构。将重复部分的代码封装成一个函数,如下所示:

      def blog_list_common_data(request, blogs_all_list):
          paginator = Paginator(
              blogs_all_list, settings.EACH_PAGE_BLOGS_NUMBER)
          page_num = request.GET.get('page', 1)  # 获取url的页码参数(GET请求)
          page_of_blogs = paginator.get_page(page_num)
          current_page_num = page_of_blogs.number  # 获取当前页码
          # 获取当前页码前后各两页的页码范围
          page_range = list(range(max(current_page_num - 2, 1), current_page_num)) + \
              list(range(current_page_num, min(
                  current_page_num + 2, paginator.num_pages) + 1))
          # 加上省略页码标记
          if page_range[0] - 1 >= 2:
              page_range.insert(0, '...')
          if paginator.num_pages - page_range[-1] >= 2:
              page_range.append('...')
    
          # 加上首页和尾页
          if page_range[0] != 1:
              page_range.insert(0, 1)
          if page_range[-1] != paginator.num_pages:
              page_range.append(paginator.num_pages)
    
          context = {}
          context['blogs'] = page_of_blogs.object_list
          context['page_of_blogs'] = page_of_blogs
          context['page_range'] = page_range
          context['blog_types'] = BlogType.objects.all()
          context['blog_dates'] = Blog.objects.dates(
              "created_time", "month", order="DESC")
          return context
  • 修改后views.py文件的内容如下所示:

      from django.shortcuts import render_to_response, get_object_or_404
      from django.core.paginator import Paginator
      from django.conf import settings
      from .models import Blog, BlogType
      # Create your views here.
    
    
def blog_list_common_data(request, blogs_all_list):
    paginator = Paginator(
        blogs_all_list, settings.EACH_PAGE_BLOGS_NUMBER)
    page_num = request.GET.get('page', 1)  # 获取url的页码参数(GET请求)
    page_of_blogs = paginator.get_page(page_num)
    current_page_num = page_of_blogs.number  # 获取当前页码
    # 获取当前页码前后各两页的页码范围
    page_range = list(range(max(current_page_num - 2, 1), current_page_num)) + \
        list(range(current_page_num, min(
            current_page_num + 2, paginator.num_pages) + 1))
    # 加上省略页码标记
    if page_range[0] - 1 >= 2:
        page_range.insert(0, '...')
    if paginator.num_pages - page_range[-1] >= 2:
        page_range.append('...')

    # 加上首页和尾页
    if page_range[0] != 1:
        page_range.insert(0, 1)
    if page_range[-1] != paginator.num_pages:
        page_range.append(paginator.num_pages)

    context = {}
    context['blogs'] = page_of_blogs.object_list
    context['page_of_blogs'] = page_of_blogs
    context['page_range'] = page_range
    context['blog_types'] = BlogType.objects.all()
    context['blog_dates'] = Blog.objects.dates(
        "created_time", "month", order="DESC")
    return context


def blog_list(request):
    blogs_all_list = Blog.objects.all()
    context = blog_list_common_data(request, blogs_all_list)
    return render_to_response('blog/blog_list.html', context)


def blogs_with_type(request, blog_type_pk):
    blog_type = get_object_or_404(BlogType, pk=blog_type_pk)
    blogs_all_list = Blog.objects.filter(blog_type=blog_type)
    context = blog_list_common_data(request, blogs_all_list)
    context['blog_type'] = blog_type
    return render_to_response('blog/blogs_with_type.html', context)


def blogs_with_date(request, year, month):
    blogs_all_list = Blog.objects.filter(
        created_time__year=year, created_time__month=month)
    context = blog_list_common_data(request, blogs_all_list)
    context['blogs_with_date'] = '%s年%s月' % (year, month)
    return render_to_response('blog/blogs_with_date.html', context)


def blog_detail(request, blog_pk):
    context = {}
    blog = get_object_or_404(Blog, pk=blog_pk)
    context['previous_blog'] = Blog.objects.filter(
        created_time__gt=blog.created_time).last()
    context['next_blog'] = Blog.objects.filter(
        created_time__lt=blog.created_time).first()
    context['blog'] = blog
    return render_to_response('blog/blog_detail.html', context)
```