Python 领域运用:Web 开发

1. Web 开发简介

1.1 Web 的历史

1989年,TimBerner 提出了一种能让远隔两地的研究者们共享知识的设想。它的基本理念是:借助多文档之间相互关联形成的超文本(HyperText),连成可相互参阅的 WWW(World Wide Web)。

在互联网早期,网站的内容是静态的,浏览相同地址的页面返回的内容不会发生变化。由于网页的内容是不发生变化的,因此早期互联网站只能用于共享静态的文档,无法实现复杂的应用。

互联网得到了飞速的发展,人们不再满足网页只有静态文本的形式,出现了动态网页的技术,例如专用于开发动态网页的 PHP 编程语言。1995 年,Rasmus Lerdorf 发明了 PHP 编程语言。PHP 是在服务器端执行脚本语言,它动态生成 HTML 文本返回给浏览器。

1.2 出现了专门的 Web 开发工程师

在互联网早期,网站中的主要内容由静态页面构成,开发一个网站并不需要太多的编程工作,网站开发人员会编写 HTML 文件即可,很多网站甚至于不需要程序员的参与。

随着互联网的发展,网站的功能越来越复杂,网站提供的功能日趋丰富,网站更像是一个本地应用程序,而不是单纯展示内容的网页。在这个时期,开发 Web 需要编写大量的程序,一个复杂的 Web 开发项目包含有数万行、甚至于数十万行的源代码。

随着网站开发的需求的增加,出现了专门的 Web 开发工程师,在计算机行业的招聘网站上搜索 "Web 开发”,可以获得大量的职位招聘信息:

图片描述

2. Web 开发入门

本节介绍进行 Web 开发所需要了解和掌握的技术。

2.1 HTML 基础

HTML称为超文本标记语言,是一种标识性的语言。它包括一系列标签.通过这些标签可以将网络上的文档格式统一,使分散的Internet资源连接为一个逻辑整体。HTML文本是由HTML命令组成的描述性文本,HTML命令可以说明文字,图形、动画、声音、表格、链接等

HTML 不是一门编程语言,而是一种用于定义内容结构的标记语言。HTML 由一系列的元素(elements)组成,这些元素可以用来包围不同部分的内容,使其以某种方式呈现或者工作。 一对标签( tags)可以为一段文字或者一张图片添加超链接,将文字设置为斜体,改变字号,等等。

学习 HTML 需要学习各种标签,例如使用 table 标签描述了一个 2 行 2 列的表格:

<table>
  <tr>
    <td>第 1 行 第 1 列</td>
    <td>第 1 行 第 2 列</td>
  </tr>
  <tr>
    <td>第 2 行 第 1 列</td>
    <td>第 2 行 第 2 列</td>
  </tr>
</table>
  • table 标签描述了一个表格
  • tr 标签描述表格中的一行
  • td 标签描述表格中的一个单元
第 1 行 第 1 列 第 1 行 第 2 列
第 2 行 第 1 列 第 2 行 第 2 列

2.2 CSS 基础

层叠样式表 (CSS) 是用来添加样式到你网站的代码。举例来说,你想让文字是黑色还是红色的?在屏幕的何处展示内容?用什么背景图像和颜色来装饰你的网站?

和 HTML 类似,CSS 也不是真正的编程语言,甚至不是标记语言。它是一门样式表语言,这也就是说人们可以用它来选择性地为 HTML 元素添加样式。举例来说,要选择一个 HTML 页面里所有的段落元素,然后将其中的文本改成红色,可以这样写 CSS:

p {
    color: red
}

2.3 Javascript 基础

JavaScript(缩写:JS)是一门完备的 动态编程语言。当应用于 HTML 文档时,可为网站提供动态交互特性。例如:检查输入的合法性、在按下按钮或收到表单数据时做出的响应等。

JavaScript 的应用场合极其广泛,简单到响应按钮点击,复杂到游戏、2D/3D 动画、大型数据库驱动程序等等。

浏览器内置的 Javascript API 提供了丰富的功能,比如:动态创建 HTML 和设置 CSS 样式、生成2D 图像与音频样本等。

2.4 使用 Python 作为 Web 后端

使用浏览器访问网站的过程如下所示:

  • 浏览器向网站发出请求
  • 网站收到请求后,返回 HTML 文本作为响应内容

在下图的例子中,服务器返回当前时间 (HTML 的格式)。使用浏览器访问网站时,显示的内容是动态的,每次都是当前时间,如下所示:

图片描述

在这个例子中,浏览器又被称为前端,服务器又被称为后端。后端收到请求后,做如下的工作:

  • 分析用户请求,获取请求的参数
  • 根据请求的参数进行处理,可能会读取数据库
  • 最终生成一段 HTML 文本返回给前端

Python 作为一个通用的编程语言,能够完成以上的工作,由于其开发效率高,在 Web 后端开发中占有重要的一席之地。以下是慕课网的课程分类目录,在后端开发的分类中,Python 和 Django (Python 的 web 框架) 占有两个条目:

图片描述

3. Web 开发框架

3.1 简介

在传统的软件开发中,框架是一种提供了可重用的公共结构的技术,为构建新的应用程序提供了极大的便利。框架是一种非常成熟的技术,在多个领域得到了成功的应用,例如:在桌面应用程序开发的领域,微软公司的 Visual Studio C++ 为应用程序生成框架,基于 VC++ 应用程序框架可以大大的提升桌面程序的开发效率。

随着 Web 开发项目的复杂度的日益提升,软件开发中的框架技术被引入到 Web 开发领域。Web 开发框架是用于进行 web 开发的一套软件架构,Web 框架为 Web 应用程序提供了基础的功能。开发人员在 Web 框架的基础上实现自己的业务逻辑,基于 Web 框架开发应用,开发人员只需要专注应用的业务逻辑,非业务逻辑的基础功能则由框架提供,从而提升开发效率。

3.2 常见的 Web 框架

目前,最流行的 Python 的 Web 开发框架是 Flask 框架和 Django 框架,截至 2019 年 9 月 2 日,Flask 在 Github 上的星数是 46179 颗,Django 的 Github 星数是 43806 颗,两者几乎难分伯仲,其它 Python Web 框架与 Flask 和 Django 星数相差甚远。

两者的主要区别在于:Django 功能大而全,Flask 只包含基本的功能。

Django 采用一站式解决的思路,Django 集成有模板、表单、路由、认证、基本的数据库管理等内建功能,开发者不用在选择应用的基础设施上花费大量时间。

Django 就像是一个装潢好的房子(如下图所示),它提供了各种家具,直接入住即可。

图片描述

Flask 相对于 Django 而言是轻量级的 Web 框架。和 Django 不同,Flask 只提供了最核心的功能,轻巧、简洁,通过定制第三方扩展来实现具体功能。

默认情况下,不包含数据库抽象、用户认证、表单验证、发送邮件等其它 Web 框架经常包含的功能。Flask依赖用各种灵活的扩展(比如邮件Flask Mail,用户认证Flask Login,数据库Flask SQLAlchemy)来给Web应用添加额外功能。

Flask 就像是一个没有装潢的房子(如下图所示),用户需要自己选择各种家具才可以入住。

图片描述

4. Web 框架提供的核心功能

4.1 路由配置

在 Web 开发过程中,经常会遇到 “路由” 的概念。简单来说,路由就是 URL 到处理函数的映射。

Web 后端处理大致流程可以看成这样:

  1. 浏览器发出请求
  2. 服务器端监听到 80 端口的请求,解析请求的 url 路径
  3. 根据服务器的路由配置,找到对应 url 对应的处理函数
  4. 运行处理函数生成一段 HTML 文本,并返回给浏览器

假设一个论坛系统由如下数据构成:

  • 主题,每个主题包含有标题和内容,使用 topicID 标识该主题
  • 用户,每个用户包含姓名和密码,使用 userID 标识该用户

论坛的域名是 www.bbs.com,它向外界提供了若干可访问的 URL:

URL 功能
http://www.bbs.com/topics/12373 访问 topicID 为 12373 的主题
http://www.bbs.com/users/1353 访问 userID 为 1353 的用户页面

在服务器端有两个处理页面函数:

  • showTopic(topicId) 显示指定 topicId 的主题内容
  • showUser(userId) 显示指定 userId 的用户信息

在下图中,当用户请求形式为 /topics/xxx 的 URL 时,服务器需要找到 showTopic 函数处理该请求;当用户请求形式为 /users/xxx 的 URL 时,服务器需要找到 showUser 函数处理该请求。

URL 到处理函数的映射,就被称为路由。Web 开发框架提供了路由配置的功能,可以方便的指定处理 URL 的函数。

4.2 模板渲染

用 Python 生成 HTML 的过程十分繁琐,需要进行字符串拼接,代码的可读性差。假设,在一个学生管理系统中,有一个页面是展示所有学生的姓名、学号等信息,Python 后端程序通过读取数据库生成一段 HTML 文本,代码如下:

def generateHtml():
    html = ''
    html += '<table>'

    sql = 'SELECT * FROM students'
    cursor.execute(sql)

    students = cursor.fetchall() 
    for student in students:
        html += '<tr>'
        html += '<td>%s</td>' % student[0]
        html += '<td>%s</td>' % student[1]
        html += '</tr>'

    html += '<table>'        

函数 generateHtml() 通过 SQL 语句读取数据,使用字符串拼接成一段 HTML 的 table,返回给浏览器。这样的方式的缺点在于:HTML 代码和 Python 代码混合在一起,程序的可读性很差。

针对以上问题,提出了模板的解决方案,实现数据与 HTML 代码分离。以下是使用 django 的模板实现展示所有的学生

<table>
  {% for student in students %}
     <tr>
        <td>{{ student[0] }}</td>
        <td>{{ student[1] }}</td>
     </tr>
  {% endfor %}
</table>  

与拼接字符串相比,使用模板生成 HTML,显著的提高了程序的可读性,Web 框架都配备了各种模板引擎,Web 开发者需要学习模板的语法。

4.3 数据库 ORM

在 Web 开发中,需要访问数据库读取相关数据返回给浏览器。通常是采用 SQL 语句访问数据库,例如下面的 SQL 语句获取 name 为张三的记录:

SELECT name, age FROM persons WHERE name = '张三'

在程序中,使用 SQL 语句访问数据,易错、不够直观。因此有人提出了 ORM 技术:把关系数据库映射为对象。

面向对象编程和关系型数据库,都是目前最流行的技术。面向对象编程把所有实体看成对象(object),关系型数据库则是采用实体之间的关系(relation)描述数据。

ORM (Object Relation Map) 是一种把关系数据库映射成对象的技术,下表总结两者之间的对应关系:

关系数据库 面向对象
数据库的表(table) 类(class)
记录(record,行数据) 对象(object)
字段(field) 对象的属性(attribute)

Python 的 Web 框架通常提供了 ORM 的功能,用于简化对数据库的访问。