django2實戰4.創建文章列表頁和詳情頁url適配自定義模型管理器在view中寫業務邏輯新建模板文件添加分頁功能

繼上篇 django2實戰3.模型的增刪改查

我們已經知道如何操作文章表的數據,接下來要將這些數據用界面顯示出來。這就需要用到django的view層負責處理http請求,並將數據傳給template模板進行渲染

url適配

首先定義列表頁與詳情頁的url, url規則如下:

django是怎麼知道將url映射到相應的python文件的?這需要我們在blog下新建urls.py文件

mysite/blog/urls.py

from django.urls import path
from . import views


app_name = 'blog'

urlpatterns = [
    path('', views.post_list, name='post_list'), # 列表頁的url規則
    path('<int:year>/<int:month>/<int:day>/<slug:post>', # 詳情頁的url規則
         views.post_detail,
         name='post_detail'),
]

然後需要在項目的urls.py中引入此文件:

mysite/mysite/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls', namespace='blog')) # 引入blog應用的url配置
]

自定義模型管理器

封裝自定義的管理器,方便檢索數據。如,博客前臺要展示的數據肯定是已發佈的,如果每次取已發佈的數據都要通過過濾條件獲取,顯得很繁瑣。可以通過自定義管理器,將已發佈的文章封裝成文章類的一個屬性。

mysite/blog/models.py

class PublishedManager(models.Manager):
    def get_queryset(self):
        return super(PublishedManager, self).get_queryset().filter(status='published')

class Post(models.Model):
    #...
    objects = models.Manager()  # 默認的管理器
    published = PublishedManager()  # 自定義的管理器

以後我們只需要調用Post.published.all()就能獲取所有已發佈的文章

在view中寫業務邏輯

mysite/blog/views.py

from django.shortcuts import render, get_object_or_404
from .models import Post


# 列表頁
def post_list(request):
    posts = Post.published.all()  # 獲取所有公開的文章
    return render(request,
                  'blog/post/list.html',
                  {'posts': posts})  # 將數據傳遞到模板文件


# 詳情頁
def post_detail(request, year, month, day, post):
    post = get_object_or_404(Post, slug=post,
                                    status='published',
                                    publish__year=year,
                                    publish__month=month,
                                    publish__day=day)
    return render(request,
                  'blog/post/detail.html',
                  {'post': post})

在view中指定了list和detail的html文件路徑,我們需要在相應位置創建html文件:

新建模板文件

☁  mysite  mkdir -p blog/templates/blog/post
☁  mysite  touch blog/templates/blog/base.html
☁  mysite  touch blog/templates/blog/post/list.html
☁  mysite  touch blog/templates/blog/post/detail.html
☁  mysite  tree blog/templates # 模板文件結構
blog/templates
└── blog
    ├── base.html 
    └── post
        ├── detail.html
        └── list.html

2 directories, 3 files
  • base.html 定義了html模板的框架,列表頁和詳情頁都繼承此文件
  • list.html 列表頁,展示文章標題、摘要
  • detail.html 詳情頁,展示文章詳情內容

html模板引用 Bootstrap4

base.html

{% load static %}
<!DOCTYPE html>
<html>
<head>
  <title>{% block title %}{% endblock %}</title>
  <link rel="stylesheet" href="{% static "css/blog.css" %}">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.1.0/css/bootstrap.min.css">
  <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://cdn.bootcss.com/popper.js/1.12.5/umd/popper.min.js"></script>
  <script src="https://cdn.bootcss.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div id="content" class="col-md-9">
                {% block content %}
                {% endblock %}
            </div>
            <div id="sidebar" class="col-md-3">
                <h3>唐詩鑑賞博客</h3>
                <p>唐詩博大精深</p>
            </div>
        </div>
    </div>
</body>
</html>

在base.html中,我們引入了樣式文件{% static "css/blog.css" %},對應的路徑是:

mysite/blog/static/css/blog.css

.container {
    margin-top: 2%;
}
div.post {
    margin-bottom: 2%;
}

關於模板語法的使用,詳情見官方文檔

list.html

{% extends "blog/base.html" %}

{% block title %}我的博客{% endblock %}

{% block content %}
    {% for post in posts %}
        <div class="post">
            <h3>
                <a href="{{ post.get_absolute_url }}" class="text-info">
                    {{ post.title }}
                </a>
            </h3>
            <div class="card">
                <div class="card-header">
                    發佈時間:{{ post.publish }}  作者:{{ post.author }}
                </div>
                <div class="card-body">
                    {{ post.body|truncatewords:5|linebreaks }}
                </div>
            </div>
        </div>
    {% endfor %}
{% endblock %}

list.html繼承了base.html, 並將內容注入到base.html中id爲content的div中

detail.html

{% extends "blog/base.html" %}

{% block title %}{{ post.title }}{% endblock %}

{% block content %}
    <h1>{{ post.title }}</h1>
    <div class="card">
        <div class="card-header">
            發佈時間:{{ post.publish }}  作者:{{ post.author }}
        </div>
        <div class="card-body">
            {{ post.body|linebreaks }}
        </div>
    </div>
{% endblock %}

啓動服務,訪問 http://127.0.0.1:8000/blog/

列表頁

點擊列表頁的文章標題,進入詳情頁,注意查看詳情頁的url

http://127.0.0.1:8000/blog/2018/9/6/jiang-jin-jiu

詳情頁

添加分頁功能

如果我們的文章數據很多,不可能一次性全部取出,這時就需要做分頁功能。

首先自行到後臺多添加幾條數據

文章

在view中增加分頁邏輯

mysite/blog/views.py

# ...
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger


# 列表頁
def post_list(request):
    object_list = Post.published.all()  # 獲取所有數據
    paginator = Paginator(object_list, 3)  # 每頁3篇文章
    page = request.GET.get('page')  # 獲取當前頁數
    try:
        posts = paginator.page(page)  # 取出當前頁數的文章
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)

    return render(request,
                  'blog/post/list.html',
                  {'page': page,
                  'posts': posts})  # 將數據傳遞到模板文件
# ...

分頁的樣式採用獨立的html頁面

新建 mysite/blog/templates/pagination.html

<ul class="pagination pagination-sm">
    {% if page.has_previous %}
        <li class="page-item"><a class="page-link" href="?page={{ page.previous_page_number }}">上一頁</a></li>
    {% endif %}
    <li class="page-item active"><a class="page-link" href="#">{{ page.number }}</a></li>
    {% if page.has_next %}
        <li class="page-item"><a class="page-link" href="?page={{ page.next_page_number }}">下一頁</a></li>
    {% endif %}
</ul>

在列表頁中引入分頁

mysite/blog/templates/blog/post/list.html

{% block content %}
    # ...
    {% include "pagination.html" with page=posts %}
{% endblock %}

瀏覽器訪問 http://127.0.0.1:8000/blog/

分頁

點擊下一頁,查看url的變化:http://127.0.0.1:8000/blog/?page=2

至此,簡易的分頁功能已完成

下一節將講解如何使用django發送郵件。如果你感興趣,請關注我的django2實戰文集

如果覺得本文對你有所幫助,點個贊,或者賞杯咖啡錢,你的認可對我很重要

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章