[实验] Django 分页展示功能的实现 (Django 版)

注意:

文中的 python 系统名、mysite 项目和 movies 应用只是站主在本次操作中随意取的名称,读者可以根据自己的喜好换成任意别的名称

正文:

步骤一:系统环境要求

1) 服务器的系统需要是 openSUSE 15.2 版本
2) 服务器要关闭防火墙
3) 服务器系统要配置好可用的软件源(最好是软件数量最多的官方版本)
4) 服务器要能够连接外网

步骤二:安装 Django

2.1 安装 Python3

[root@python ~]# zypper -n install python3

(补充:在此次操作发生时,最新的 python 版本是 3.6.12)

2.2 创建并进入 Django 项目的目录

[root@python ~]# mkdir project
[root@python ~]# cd project

2.3 将 Django 项目的目录指定为 Django 环境

[root@python project]# python3 -m venv django_env

2.4 进入 Django 环境

[root@python project]# source django_env/bin/activate
(django_env) [root@python project]# pip install django

(补充:在此次操作发生时,最新的 Django 版本是 3.2)

步骤三:创建 mysite 项目

3.1 创建 mysite 项目

(django_env) [root@python project]# django-admin startproject mysite

3.2 mysite 项目的目录

3.2.1 安装 tree 目录显示软件
(django_env) [root@python project]# zypper -n install tree
3.2.2 显示 mysite 项目的目录
(django_env) [root@python project]# cd mysite
(django_env) [root@python mysite]# tree
.
├── manage.py
└── mysite
    ├── __init__.py
    ├── asgi.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

1 directory, 5 files
3.3.3 Django 项目目录介绍

1) mysite 此 Django 项目的容器
2) manage.py 命令行工具,与 Django 项目进行交互
3) mysite/__init__.py 空文件,通知 Python 此项目是 1 个 Python 包
4) mysite/settings.py 此 Django 项目的配置文件
5) mysite/urls.py 此 Django 项目的 URL 声明和 Django 的网站“目录”
6) mysite/wsgi.py WSGI 兼容 Web 服务器的入口

步骤四:创建 movies 应用

4.1 创建 movies 应用

(django_env) [root@python mysite]# django-admin startapp movies

4.2 movies 应用的目录

4.2.1 显示 movies 应用的目录
(django_env) [root@python mysite]# tree
.
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── movies
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

3 directories, 13 files
4.2.2 Django 应用目录介绍

1) movies/app.py 此 Django 应用的容器
2) movies/__init__.py 空文件,通知 Python 此项目是 1 个 Python 包
3) movies/admin.py 此 Django 应用自带的后台管理相关的类
4) movies/app.py 此 Django 应用指定应用名的文件
5) movies/migrations.py 此 Django 应用通过 python 代码生成数据库表时里面会产生一些迁移文件
6) movies/models.py 可以在里面创建一些 Python 对象并通过这些对象在数据库里创建对应的表
7) movies/test.py 此 Django 应用的测试文档
8) movies/views.py 此 Django 应用的视图,接收前端数据,把数据传递给后端,响应相关页面

4.3 在 mysite 应用中导入 movies 应用

在 mysite/mysite/settings.py 中添加以下内容:

......
INSTALLED_APPS = [
......
    'movies',
]
......

步骤五:实现 movies 应用的层级多链接

创建 mysite/movies/urls.py 并添加以下内容:

#coding=utf-8
from django.conf.urls import url, include
from users.views import register

urlpatterns = [
    url(r'^movies/', include('movies.urls')),
]

(补充:这里以设置 /movies/ 链接对应 movies 应用的链接为例)

步骤六:搭建用于 Django 的 MariaDB 数据库环境

6.1 安装 MairaDB 数据库和客户端

(django_env) [root@python mysite]# zypper -n install mariadb mariadb-devel mariadb-server mariadb-client

6.2 创建用于 Django 的 MairaDB 的库、表、数据和用户并插入测试数据

6.2.1 进入 MairaDB 数据库
(django_env) [root@python mysite]# mysql -h 127.0.0.1 -p
6.2.2 创建用于 Django 的库
MariaDB [(none)]> create databases movies;

(补充:这里以创建 movies 库为例)

6.2.3 创建用于 Django 的表
6.2.3.1 进入用于 Django 到库
MariaDB [(none)]> use movies;

(补充:这里以进入 moives 库为例)

6.2.3.2 创建用于 Django 的表
MariaDB [movies]> create table movies(mid INT AUTO_INCREMENT,mname VARCHAR(100) NOT NULL,mdesc TEXT,mimg VARCHAR(120) NOT NULL,mlink VARCHAR(200) NOT NULL,PRIMARY KEY( mid ),UNIQUE( mname ));
Query OK, 0 rows affected (0.058 sec)


补充:这利以创建
1) mid 是 INT 字段,且自动增加
2) mname 是 VARCHAR 字段,长度为 100,且非空
3) mdesc 是 TEXT 字段,长度为 120,且非空
4) mlink 是 VARCHAR 字段,长度为 200,且非空
5) mid 为主键
6) mname 不能重复
为例

6.2.3.3 查看刚创建的表的表结构
MariaDB [movies]> desc movies; 
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| mid   | int(11)      | NO   | PRI | NULL    | auto_increment |
| mname | varchar(100) | NO   | UNI | NULL    |                |
| mdesc | text         | YES  |     | NULL    |                |
| mimg  | varchar(120) | NO   |     | NULL    |                |
| mlink | varchar(200) | NO   |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
5 rows in set (0.001 sec)

(补充:这里以查看 movies 表的表结构为例)

6.2.4 创建用于 Django 的数据
6.2.4.1 进入用于 Django 到库
MariaDB [(none)]> use movies;

(补充:这里以进入 moives 库为例)

6.2.4.2 创建用于 Django 的数据
MariaDB [movies]> insert into movies (mname,mdesc,mimg,mlink) VALUES("Titanic","Accidents and love story, UHD, Dolby Vision,Dolby Atmos","eternalcenter.com/titanic/image","eternalcenter.com/titanic");
Query OK, 1 row affected (0.008 sec)
MariaDB [movies]> 
MariaDB [movies]> insert into movies (mname,mdesc,mimg,mlink) VALUES("World War","Science fiction, UHD, Dolby Vision,Dolby Atmos","eternalcenter.com/world-war/image","eternalcenter.com/world-war");
Query OK, 1 row affected (0.008 sec)
MariaDB [movies]> 
MariaDB [movies]> insert into movies (mname,mdesc,mimg,mlink) VALUES("Maleficent","Magic, UHD, Dolby Vision,Dolby Atmos","eternalcenter.com/maleficent/image","eternalcenter.com/maleficent");
Query OK, 1 row affected (0.012 sec)
MariaDB [movies]> 
MariaDB [movies]> insert into movies (mname,mdesc,mimg,mlink) VALUES("Cars","Animation, UHD, Dolby Vision,Dolby Atmos","eternalcenter.com/cars/image","eternalcenter.com/cars");
Query OK, 1 row affected (0.011 sec)
MariaDB [movies]> 
MariaDB [movies]> insert into movies (mname,mdesc,mimg,mlink) VALUES("News","Animation, UHD, Dolby Vision,Dolby Atmos","eternalcenter.com/news/image","eternalcenter.com/news");
Query OK, 1 row affected (0.011 sec)

(补充:这里以符合 movies 表结构的规范,随意向 movies 插入 5 条数据为例)

6.2.4.3 查看刚刚创建的数据
MariaDB [movies]> select * from movies;
+-----+------------+---------------------------------------------------------+------------------------------------+------------------------------+
| mid | mname      | mdesc                                                   | mimg                               | mlink                        |
+-----+------------+---------------------------------------------------------+------------------------------------+------------------------------+
|   1 | Titanic    | Accidents and love story, UHD, Dolby Vision,Dolby Atmos | eternalcenter.com/titanic/image    | eternalcenter.com/titanic    |
|   3 | World War  | Science fiction, UHD, Dolby Vision,Dolby Atmos          | eternalcenter.com/world-war/image  | eternalcenter.com/world-war  |
|   4 | Maleficent | Magic, UHD, Dolby Vision,Dolby Atmos                    | eternalcenter.com/maleficent/image | eternalcenter.com/maleficent |
|   5 | Cars       | Animation, UHD, Dolby Vision,Dolby Atmos                | eternalcenter.com/cars/image       | eternalcenter.com/cars       |
|   6 | News       | Animation, UHD, Dolby Vision,Dolby Atmos                | eternalcenter.com/news/image       | eternalcenter.com/news       |
+-----+------------+---------------------------------------------------------+------------------------------------+------------------------------+
5 rows in set (0.000 sec)

(补充:这里以查看 movies 表里的所有数据为例)

6.2.5 创建用于 Django 的用户
6.2.5.1 创建用于 Django 到用户
MariaDB [(movies)]> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;

(补充:这里以创建 root 用户,密码是 password 为例)

6.2.5.2 刷新权限
MariaDB [(movies)]> flush privileges;

6.3 退出 MariaDB 数据库

MariaDB [(none)]> exit

6.4 重启 MariaDB 数据库

(django_env) [root@python mysite]# systemctl restart mariadb

步骤七:实现连接 MariaDB 数据库

7.1 安装 Django 连接 MariaDB 的模块

(django_env) [root@python mysite]# pip3 install hexdump
(django_env) [root@python mysite]# pip3 install pymysql

7.2 在 mysite 应用中添加 Django 连接 MariaDB 的模块

在 mysite/mysite/__init__.py 中添加以下内容:

......
import pymysql
pymysql.install_as_MySQLdb()

7.3 在 mysite 应用中设置连接到 MariaDB 数据库

将 mysite/mysite/settings.py 中的以下内容:

......
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}
......

修改为:

......
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'movies',
        'HOST': '127.0.0.1’,
        'PORT': '3306',
        'USER': 'root',
        'PASSWORD': 'password',
    }
}
......


补充:这里以
1) 使用的库是 movies
2) 使用的服务器是 127.0.0.1
3) 使用的端口是 3306
4) 使用的用户是 root
5) 使用的密码是 password
为例

步骤八:根据数据库表结构生成 Django 数据库模型

(django_env) [root@python mysite]# python3 manage.py inspectdb>movies/models.py

步骤九:实现分页展示功能

9.1 在 movies 应用中添加 1 个分页展示功能的 HTML 模板

创建 mysite/movies/templates/movies/index.html 并添加以下内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        <!--avoid collapse after floating-->
        .clearfix{
                zoom:1;
        }
        .clearfix:after{
                content: "";display: block;visibility: hidden;line-height: 0;clear: both;
        }

        body,div{
            margin:0 auto;
        }

        div{
            border:1px solid gray;
            width:750px;
            text-align: center;
        }

        ul{
            list-style-type: none;
            display: inline-block;
        }


        #header li{
            float: left;
            margin-left:10px;
            font-size:16px;
            font-family: 'Microsoft elegant black';
            color: #666666;

        }
        #header li:hover{
            cursor: pointer;
            background:blue;
            color: white;
        }

        #content li{
            float: left;
            display: inline;
            margin-right:15px;
            text-align: center;
            height:225px;
            overflow: hidden;
            padding-top:10px;
            padding-bottom:5px;

        }
        #content h1{
            font-size:14px;
            margin:0;

        }

        .tip{
            display: block;
            font-size:12px;
        }

       .h1,.tip{
            width:110px;
           text-align: center;
        }
        
        #content ul{
            /*remove the inner and outer margins of UL*/
            margin:0;
            padding:0;

        }
    </style>

</head>
<body>
    <div id="header"  class="clearfix">
        <ul class="clearfix">
            <li>home page</li>
            <li>record</li>
            <li>love</li>
            <li>ethic</li>
            <li>comic</li>
            <li>science fiction</li>
            <li>history</li>
            <li>warfare</li>
            <li>short film</li>
            <li>natural</li>
        </ul>
    </div>
    <div id="content" >
        <ul class="clearfix">
            {% for movie in nowpage %}
                <li>
                    <a href="{{ movie.mlink }}"><img src="{{ movie.mimg }}"/></a>
                    <h1 class="h1">{{ movie.mname }}</h1>
                    <span class="tip">{{ movie.mdesc }}</span>
                </li>
            {% endfor %}
        </ul>
    </div>
    <div>
        {% if nowpage.has_previous %}
            <a href="/movies/?page={{ nowpage.previous_page_number }}">prepage</a>
        {% endif %}
        <!--show previous page when current page exists-->
        {% if nowpage.has_next %}
            <a href="/movies/?page={{ nowpage.next_page_number }}">nextpage</a>
        {% endif %}
        <!--display the next page when it exists-->
    </div>
</body>
</html>


补充:这里主要以
1) 生成 1 个展示每条数据的 mlink 字段、mimg 字段、mname 字段 和 mdesc 字段的表格,且每条数据就是 1 个表格
2) 在当前页的前提下,如果有前 1 页或后 2 页,则显示出来并为其设置对应的链接
为例

9.2 在 movies 应用中添加 1 个网页返回值的模块并实现所需功能

在 mysite/movies/views.py 中添加以下内容:

......
from .models import Movies
from django.core.paginator import Paginator,PageNotAnInteger,EmptyPage
......
def movies(request):

    page = request.GET.get('page',1)
    # receive the request parameter page, and when the page value does not exist, its value is 1

    page = int(page)
    # force num to integer

    movies = Movies.objects.all()
    # import all the data in the database corresponding to the Movies module into the movies variable

    items = Paginator(movies,3)
    # creating a pager object
 
    try:
        nowpage = items.page(page)
        # get the data of the current page
    except PageNotAnInteger:
        nowpage = items.page(1)
        # when page is not a numeric value, the data of the first page is returned
    except EmptyPage:
        nowpage = items.page(items.num_pages)
        # when the number of pages corresponding to the value of page does not exist, the data of the last page is returned

    return render(request,'movies/index.html',{'items':items,'nowpage':nowpage})


补充:这里主要以:
1) 设置 movies 模块并返回 movies/index.html
2) 从 movies/index.html 中获取 page 值,且当 page 值不存在时,其默认值为 1,并将其强行转换成整数
3) 这里的 movies = Movies.objects.all() 是指将 Movies 模块对应数据库里的所有数据导入给 movies 变量
4) 调用 Paginator 模块将 movies 变量生成每页为 3 条数据的分页的 items 对象,并将当前页数据赋予给 nowpage 变量
5) 调用 PageNotAnInteger 模块当页码不是一个数值时返回页码是 1 的数据
6) 调用 EmptyPage 模块当页码不存在时返回最后一页的数据
7) 给予 movies/index.html items 和 nowpage 变量,同时将对应的值赋予给它们
为例

9.3 在 movies 应用中添加 1 个链接并设置对应的模块

创建 mysite/movies/urls.py 并添加以下内容:

#coding=utf-8
from django.conf.urls import url
from movies.views import movies

urlpatterns = [
    url(r'^$', movies),
]

(补充:这里以设置空链接链接对应 movies 模块为例)

步骤十:启动 Django 服务

(django_env) [root@python mysite]# python3 manage.py runserver

步骤十一:测试分页展示功能

1) 打开浏览器输入以下网址:

http://127.0.0.1:8000/movies/

2) 可以看到对应的展示模版有 3 条数据并且可以向下和向上翻页