前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >开源图书《Python完全自学教程》12.3制作网站

开源图书《Python完全自学教程》12.3制作网站

作者头像
老齐
发布2022-12-09 20:23:00
8540
发布2022-12-09 20:23:00
举报
文章被收录于专栏:老齐教室

12.3 制作网站

网站,现在可谓是司空见惯,就连本书作者也有个人网站(www.itdiffer.com),用以向读者提供所编写书籍的参考资料。那么,怎么制作网站?如果从理论上说,这是一个听起来、讲起来都比较复杂的事情。首先要全面了解有关计算机网络的有关知识(推荐阅读《计算机网络》,谢希仁编著,电子工业出版社出版),然后要能够运用多项技术,比如搭建服务器并部署有关程序、创建数据库、编写网站代码(还分前端和后端)、配置网站域名等,甚至还要考虑网站的并发量、安全性。所以,通常制作网站的项目,都是由若干个人组成一个团队协作完成。

不过,随着技术发展,制作网站的技术门槛正在不断降低,很多底层的东西都被“封装”和“模块化”,开发者将更多精力集中在网站的功能上。这就类似于 Python 中的包和模块一样,比如12.2.2 节中使用的 sqlite3 模块,我们不需要了解其内部工作机制,关注点在于用它实现数据库的连接和操作。

Python 生态中,提供了很多制作网站的包——更习惯的说法是Web框架(Web Framework),比如 Web.py 、Tornado 、Flask 、Django 等,不同框架会有各自的特点,很难用“好、坏”这种简单标准来评价——有的人热衷于“二进制”思维,但愿本书读者不要陷入“0/1”口水战。

下面使用 Django 框架,简要演示用它快速制作网站的流程。

Django 的官方网站(https://www.djangoproject.com/)上显示,撰写本节内容时所发布的最新版是 Django 3.2.5 ,此前 Django 有过 2.x 和 1.x 的各个版本。读者在阅读到本书并调试代码的时候,或者阅读其他有关资料时,务必注意版本问题,不同版本之间会有所差异。此外,围绕 Django 框架还有很多第三方插件(亦即 Python 语言的包或模块),它们也有所适用的版本。

其实,在第11章11.5节,已经在虚拟环境中安装了 Django ,下面就启动该虚拟环境,在其中用 Django 框架制作网站。

12.3.1 创建项目

Django 中的项目(Project)可以看做是一个专有名词,后面还有一个与之有关的名词应用(Application)。所谓项目,可以理解为一个网站。

在虚拟目录 myvenv 内,创建一个 Django 项目(要确认已经进入虚拟环境,参阅第11章11.5节),执行如下指令(本节演示中所有操作系统指令,均为 Linux 指令,请使用 Windows 系统的读者注意):

代码语言:javascript
复制
(myvenv) myvenv % ls
bin  include  lib  pyvenv.cfg
(myvenv) myvenv % django-admin startproject mysite
(myvenv) myvenv % ls
bin  include  lib  mysite  pyvenv.cfg

指令 django-admin startproject mysite 创建名为 mysite 的项目,执行此指令后,在当前目录中新增了 ./mysite 子目录。这个子目录并非是空的,Django 会默认为其添加如下内容(以下显示此时 ./mysite 的结构):

代码语言:javascript
复制
(myvenv) myvenv % tree mysite
mysite
├── manage.py
└── mysite
    ├── __init__.py
    ├── asgi.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

1 directory, 6 files

然后进入到项目的子目录中,执行 manage.py 程序:

代码语言:javascript
复制
(myvenv) myvenv % cd mysite
(myvenv) mysite % python manage.py runserver
Watching for file changes with StatReloader
... (省略其他显示信息)
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

这样我们就把一个基于 Django 的网站跑起来了,由提示信息可知:

  • 可以通过 http://127.0.0.1:8000/ 访问本网站;
  • 结束当前服务的方法是按 Ctrl-C 组合键。

打开浏览器,在地址栏中输入 http://127.0.0.1:8000 或者 http://localhost:8000 ,就会看到图12-3-1所示界面。

图12-3-1 网站默认首页

就这样,已经创建了一个非常简单的网站——好像挺容易的呀。

12.3.2 创建应用

项目已经创建好,网站也有了,接下来要实现网站的具体功能。在 Django 中,人们把这些具体的功能称为应用(Application)。

结束图12-3-1所示的服务(按“Ctrl-C”组合键),继续在虚拟目录中执行如下操作:

代码语言:javascript
复制
(myvenv) mysite % ls
db.sqlite3 manage.py mysite

与12.3.1节所看到的 ./mysite 目录结构相比较,这里多了一个文件 db.sqlite3 ,这个文件就是12.2.2节所介绍过的 SQLite 数据库文件,Django 默认使用此类型的数据库,本节的浮光掠影地演示中,也使用这个数据库。

在当前目录中,继续执行:

代码语言:javascript
复制
(myvenv) mysite % python manage.py startapp book
(myvenv) mysite % ls
book  db.sqlite3 manage.py mysite

指令 python manage.py startapp book 创建一个名为 book 的应用,并在当前目录中以子目录 ./book 的形式表现。这个子目录中也不是空的,默认配置如下:

代码语言:javascript
复制
(myvenv) mysite % tree book
book
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│   └── __init__.py
├── models.py
├── tests.py
└── views.py

1 directory, 7 files

如果把应用理解为项目的子集,当应用创建好之后,就需要向项目“汇报”存在此应用了。用 IDE 工具打开项目目录中的 ./mysite/settings.py 文件(如12.3.1节中执行 tree mysite 后的显示的目录结构),找到第 33 行,对 INSTALLED_APPS 的值做如下修改:

代码语言:javascript
复制
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'book',    # 增加一个应用
]

如此就完成了应用的配置——不要忘记保存文件。

12.3.3 数据模型类

一般的动态网站(与之对应的是“静态网站”)都有数据库。Django 为了简化开发,让开发者用 Python 语言可以实现一切,于是对数据库操作提供了 ORM 技术,即 Object-Relational Mapping(对象关系映射)。ORM 的作用是在关系型数据库和业务实体对象之间进行映射,这样在操作业务对象时,就不需要再去和复杂的 SQL 语句打交道,只需简单地操作对象的属性和方法。

Django 的 ORM 实现方式就是编写数据模型类,这些类可以写到任何文件中,通常写在每个应用的models.py 文件中。每个数据模型类都是 django.db.models.Model 的子类。应用的名称(小写字母)和数据模型类的名称(小写字母)共同组成一个数据库表的名称。

用 IDE 打开 ./book/models.py 文件,并编写如下数据模型类:

代码语言:javascript
复制
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User

class Articles(models.Model):
    title = models.CharField(max_length=300)                     # (1)
    body = models.TextField()
    publish = models.DateTimeField(default=timezone.now)
    class Meta:                                                  # (2)
        ordering = ("-publish",)
    def __str__(self):
        return self.title

Articles 中的 titleauthorbodypublish 是类属性,对应着数据库表的字段。每个类属性的类型(即字段类型)由等号右侧定义——可以理解为类属性的初始值为等号右侧的实例。例如注释(1)中,类属性(字段)title 引用了实例 models.CharField(max_length=300) —— CharField() 类型,并且以参数 max_length=300 的形式说明字段的最大数量。

注释(2)从名称上看貌似 Python 中的元类,但它跟元类不同。在此处,通过 ordering = ("-publish",) 规定了 Articles 实例对象的显示顺序,负号表示按照 publish 字段值的倒序显示。

数据模型类 Articles 编写好之后,再执行如下操作,从而在数据库中创建对应的表结构:

代码语言:javascript
复制
# 第一步
(myvenv) mysite % python manage.py makemigrations
Migrations for 'book':
  book/migrations/0001_initial.py
    - Create model Articles

# 第二步
(myvenv) mysite % python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, book, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying book.0001_initial... OK
  Applying sessions.0001_initial... OK

以上操作完成之后,已经在数据库 db.sqlite3 中创建了多个表,其中包括 Articles 类对应的表,图12-3-2显示的是当前已经有的表(其他表都是 Django 默认创建的。图示所用工具仍然是 12.2.2 节用过的软件)

图12-3-2 Article 对应的表结构

12.3.4 发布文章

用 Django 默认的管理功能可以在已经创建的网站上发布文章。要使用此功能,必须先创建超级管理员。

代码语言:javascript
复制
(myvenv)  mysite % python manage.py createsuperuser
Username (leave blank to use 'qiwsir'):

注意执行上述指令的位置,在项目目录中,即 manage.py 文件所在位置。输入用户名:

代码语言:javascript
复制
(myvenv) mysite % python manage.py createsuperuser
Username (leave blank to use 'qiwsir'): admin
Email address:

再输入邮箱(只要符合邮箱格式就行):

代码语言:javascript
复制
(myvenv) mysite % python manage.py createsuperuser
Username (leave blank to use 'qiwsir'): admin
Email address: admin@laoqi.com
Password:

输入密码。注意密码不能太简单,若太简单,系统会给予友好提示。输入一遍之后,再验证一遍,最终出现:

代码语言:javascript
复制
(myvenv) qiwsir@qiwsirs-MacBook-Pro mysite % python manage.py createsuperuser
Username (leave blank to use 'qiwsir'): admin
Email address: admin@laoqi.com
Password:
Password (again):
Superuser created successfully.

则超级管理员创建完毕——请牢记用户名和密码。

然后运行服务器。

代码语言:javascript
复制
(myvenv) qiwsir@qiwsirs-MacBook-Pro mysite % python manage.py runserver
Watching for file changes with StatReloader
...
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

在浏览器的地址栏中输入 http://127.0.0.1:8000/admin/ ,打开图12-3-3所示的界面。

图12-3-3 管理端登录界面

输入刚才创建的超级管理员的用户名和密码进入系统,如图12-3-4所示。

图12-3-4 管理界面

Groups 和 Users 是 Django 在用户管理应用中默认的两项。单击 Users 会看到当前项目仅有的一个用户 admin,当然可以增加用户,读者一定要试一试。

目前暂不研究用户问题,重点在于发布文章。但是目前还找不到发布文章的地方。

稍安勿躁。用 IDE 打开 ./book/admin.py 文件,输入如下代码,并保存文件。

代码语言:javascript
复制
from django.contrib import admin
from .models import Articles

admin.site.register(Articles)

在调试状态下,如果没有新增加的文件,只是修改了原有文件,则不需要重新启动 Django 服务(如果 Django 服务没有启动,请确保启动)。刷新图12-3-4所示的页面,即可看到图12-3-5所示的效果。

图12-3-5 增加对 book 应用的管理

点击“Add”按钮可以添加文章,如图12-3-6所示所示。

图12-3-6 编辑文章

然后点击“SAVE”按钮即可保存此文章。有兴趣可以多发布几篇。

发布文章的目的是给别人看,别人怎么看?接下来解决这个问题。

12.3.5 文章标题列表

根据阅读网站上文章的经验,一般是有一个页面显示文章标题,然后点击标题,呈现该文章的完整内容。本节首先做一个显示标题列表的页面。

用 IDE 打开 ./book/views.py 文件,编写一个能够从数据库中已存储的文章标题的函数——在 Django 中称之为视图函数

代码语言:javascript
复制
from django.shortcuts import render
from .models import Articles

def book_title(request):  
    posts = Articles.objects.all()  
    return render(request, "book/titles.html", {"posts":posts})  

函数 book_title() 的参数是 request ,这个参数负责响应所接收到的请求且不能缺少,并总是位于第一的位置。除这个不可或缺的参数外,还可以根据需要在其后增加别的参数。

return 语句中的 render() 函数的作用是将数据渲染到指定模板上(关于模板,见下文内容)。render() 的第一个参数必须是 request ,然后是模板位置和所传送的数据,数据是用类字典的形式传送给模板的。

render() 中出现的 book/titles.html 就是标题列表的前端展示页面——被称为“模板”。在每一个应用中都可以有一个专门的模板目录。进入应用 book 的目录 ./book ,建立一个子目录 ./templates ,名称和位置必须如此,再按照如下方式建立有关文件和子目录。

代码语言:javascript
复制
(myvenv) book % tree templates
templates
└── book
    └── titles.html

1 directory, 1 file

templates 目录是 Django 默认的存放本应用所需模板的目录,如果不用自定义的方式指定模板位置,Django 会在运行时自动来这里查找 render() 函数中所指定的模板文件。

然后编写 titles.html 文件的代码,这不是 Python 程序文件,是 HTML 文件,关于它的知识超出本书范畴,读者可以参考有关资料(在此处,可以照抄如下代码)。

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    <meta charset="utf-8">
    <meta  name="viewport" content="width=device-width, initial-scale=1">
    <title>my website</title> 
    <!-- Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
</head>

<body>
<div class="container">
<center><h1>老齐的书</h1></center>
    <div class="row">
        <div class="col-md-8">
            <ul>
            {% for post in posts %} 
                <li>{{ post.title }}</li> 
            {% endfor %}
            </ul>
        </div>
        <div class="col-md-4">
            <h2>老齐教室</h2>
            <p>欢迎访问我的网站:www.itdiffer.com</p>
            <p>包括各种学习资料</p>
        </div>
    </div>
</div>
<!-- Bootstrap 核心 JavaScript 文件 -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>
</body>
</html>

视图函数和模板都编写好之后,要想通过网页访问,还需要进行 URL 配置。首先要配置 ./mysite/urls.py ,在这个文件中配置本项目的各个应用。

代码语言:javascript
复制
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('book/', include("book.urls"), name='book'),
]

然后在 book 目录中创建文件 urls.py ,并写入如下代码:

代码语言:javascript
复制
from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.book_title, name="book_title"),
]

重启 Django 服务,在浏览器中输入 http://127.0.0.1:8000/book/ ,会看到图12-3-7所示界面,显示了文章标题。

图12-3-7 显示文章标题的界面

12.3.6 查看文章内容

每一篇文章,在数据库中都会有唯一的 id,因此可以通过文章 id 从数据库中读出该文章,并显示与网页上。

按照用户的操作顺序,在 titles.html 页面中显示的标题应该有超链接,点击该超链接即向服务器请求显示该标题的文章,所以,应该在 titles.html 中显示标题的部分做如下修改。

代码语言:javascript
复制
<ul>
    {% for post in posts %} 
        <li><a href="{{post.id}}">{{ post.title }}</a></li> \\ 修改
    {% endfor %}
</ul>

而后编辑 ./book/views.py ,增加响应查看文章请求的视图函数 book_article()

代码语言:javascript
复制
def book_article(request, article_id):
    article = Articles.objects.get(id=article_id)
    return render(request, 'book/content.html', {"article": article})

视图函数 book_article 的参数除了 request 之外,还有 article_id ,这个参数需要通过前端的请求获得,在后续的 URL 配置中会给予实现。

然后编写展示文章内容的模板文件 ./templates/book/content.html 文件,代码如下:

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    <meta charset="utf-8">
    <meta  name="viewport" content="width=device-width, initial-scale=1">
    <title>my website</title> 
    <!-- Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
</head>

<body>
<div class="container">
<center><h1>老齐的书</h1></center>
    <div class="row">
        <div class="col-md-8">
            <center><h2>{{article.title}}</h2></center>
            <center>{{article.publish}}</center>
            <p class="lead">{{article.body}}</p>
        </div>
        <div class="col-md-4">
            <h2>老齐教室</h2>
            <p>欢迎访问我的网站:www.itdiffer.com</p>
            <p>包括各种学习资料</p>
        </div>
    </div>
</div>
<!-- Bootstrap 核心 JavaScript 文件 -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>
</body>
</html>

接着配置 URL,因为还是针对 book 这个应用而言,所以不需要修改 ./mysite/urls.py ,只需要在 ./book/urls.py 文件中增加新的 URL 路径。

代码语言:javascript
复制
from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.book_title, name="book_title"),
    url(r'(?P<article_id>\d)/$', views.book_article, name='book_content'), # new
]

视图函数 book_article(request, article_id) 的参数 article_id ,用于获得 URL 中每篇文章的 id,即 ./book/templates/book/titles.html 文件中的超链接 <a href='{{title.id}}'> 所产生的请求地址中最后的数字,例如 http://127.0.0.1/blog/1/ 。因此,使用 r'(?P<article_id>\d)/$' 这种方式,得到该请求的 id 数值并赋值给参数 article_id

现在访问文章标题网页,则所发布的文章已经具有了超级链接(要养成习惯,每次测试效果时,都要查看 Django 是否启动了),点击该标题,即可显示如图12-3-8所示的文章详情页。

图12-3-8 文章详情页

至此,以不求甚解的精神和实践,制作了一个非常简陋的网站——严格地说,是编写了网站源码。要想让这个网站能够成为万维网上的一员,还需要做很多工作,不过那些不是本书要介绍的了,有兴趣的读者可以参考有关资料。

自学建议 制作网站,是软件开发中一个非常普遍的领域,又由于网站的用途和功能、性能要求各异,也出现了各类不同的技术形态,每种技术还会对应专门化的岗位及具有相应专业技能的从业者。

  • 目前常用于网站开发的编程语言包括 PHP、Java、Python、C#、JavaScript等等(此处仅列举常见几种,事实上远不止所列几项)——选用哪一种语言,是一个争论不休的话题。
  • 有的网站,可以用工具软件生成(即使不懂编程语言也能做网站),比如常见的 WordPress(基于 PHP )等。有的网站是静态的(只发布多媒体信息,没有用户注册、登录、用户发布个人信息等功能),比如我的个人网站(www.itdiffer.com )就是利用 GitBook 制作的静态网站。
  • 动态网站(本节所演示的就是一个动态网站)还必须配备数据库,常用的关系型数据库,如 PostgreSQL、MySQL 等。非关系型数据库近年也开始在网站中使用,比如 MongoDB 等。
  • 如果对网站的界面要求比较高,通常要有专门开发前端的工程师和 UI 设计工程师。前端工程师所要掌握的技能包括但不限于 HTML、CSS、JavaScript,以及各种前端开发框架,如 Vue.js 等(前端开发框架发展变化很快,或许过几年 Vue.js 已经成为了历史)。UI 设计工程师通常要会熟练使用各种图片处理工具,并且要有较高的审美和设计能力。
  • 开发好的网站最终要部署到服务器上,目前比较常见的做法是部署到云服务器上,同时要利用诸如 Ngnix 等服务器软件系统,并对网站做各种配置。这也是一项专业技能,特别是在网站的性能、安全性等方面有较高要求的时候。

以上仅仅列出制作和发布网站所涉及到的主要方面,还有很多其他内容,比如网站源码管理、网站测试、网站开发流程、网站功能设计等。总而言之,制作网站是一项综合性很强的系统工程,需要多个技能配合应用(大型项目就把每个技能落实到专业人员上)。 有志于从事 Web 开发的读者,不妨参考上述介绍,在自学完本书内容之后,向着选定的专业技能方向发展。 如果读者愿意以 Django 框架作为 Web 开发的学习起点(这个选择很明智),可以参阅拙作《跟老齐学Python:Django 实战(第二版)》(电子工业出版社)。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-08-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老齐教室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 12.3 制作网站
    • 12.3.1 创建项目
      • 12.3.2 创建应用
        • 12.3.3 数据模型类
          • 12.3.4 发布文章
            • 12.3.5 文章标题列表
              • 12.3.6 查看文章内容
              相关产品与服务
              数据库
              云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档