001.初识Django
一:Web框架介绍
框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以快速帮你开发特定的系统。
Web框架是别人已经设定好的一个web网站模板,你学习它的规则,然后“填空”或“修改”成你需要的样子。简单说,就是你用别人搭建好的舞台来表演。
一般Web框架的架构这样的:
其他基于Python的Web框架,图tornado,flask,webpy都是在这个范围内进行增删裁剪的。例如tornado用的是自己的异步非阻塞“wsgi”,flask则只提供了最精简和基础的框架。Django则是直接使用了WSGI,并实现了大部分功能。
Web开发是Python语言应用领域的重要部分,也是工作岗位比较多的领域。如果你对基于Python的Web开发有兴趣,正打算开始学习使用Python做Web开发,或者已经是一个Web开发者有工作需要,要做Web服务,自动化运维,数据的图形化展示等,那么学习一门基于Python的Web开发框架是必修课。
二:都有那些框架?
Python下有许多款不同的Web框架。在其二十多年的历史中出现了数十种Web框架,比如Django,Tornado,Flask,Twisted,Bottle和Web.py等,他们历史悠久,有的发展迅速,还有的已经停止维护了。Django是重量级选手中最有代表性的一位。许多成功的网站和APP都基于Django。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
Django: Py Web应用开发框架 Diesel:基于Greenlet的事件I/O框架 Flask:一个用Py编写的轻量级Web应用框架 Cubes:轻量级Py OLAP框架 Kartograph.py:创造矢量地图的轻量级Py框架 Pulsar:Py的事件驱动并发框架 Web2py:全栈式Web框架 Falcon:构建云API和网络应用后端的高性能Py框架 Dpark:Py版的Spark Buildbot:基于Py的持续集成测试框架 Zerorpc:基于ZeroMQ的高性能分布式RPC框架 Bottle: 微型Py Web框架 Tornado:异步非阻塞IO的Py Web框架 webpy: 轻量级的Py Web框架 Scrapy:Py的爬虫框架 |
三:为什么选择Django?
首先介绍一下Django,Django具有以下特点:
- 功能完善,要素齐全:该有的,可以没有的都有,自带大量常用工具和框架,无须你自定义,组合,增删及修改。
- 完善的文档:经过十多年的发展和完善,Django有广泛的实践案例和完善的在线文档,开发者遇到问题时可以搜索在线文档寻找解决方案。
- 强大的数据库访问组件:Django的Model层自带数据库ORM组件,使得开发者无需学习其他数据库访问技术(SQL,pymysql,SQLALchemy等)
- 灵活的URL映射:Django使用正则表达式管理URL映射,灵活性高。新版的2.0,进一步提高了URL编写的优雅型。
- 丰富的Template模板语言:类似jinjia模板语言,不但原生功能丰富,还可以自定义模板标签,并且与其ORM的用法非常相似。
- 自带后台管理系统admin:只需要通过简单的几行配置和代码就可以实现一个完整的后台数据管理控制平台
- 完整的错误信息提示:在开发调试过程中如果出现运行错误或者异常,Django可以提供非常完整的错误信息帮助定位问题
四:基于Python进行Web开发的技术栈
要想熟练地使用Django进行Web开发,设计生产环境可用的,能够应对一定规模访问量的Web应用,开发者要学会的远远不止Django本身。Python基础,环境搭建,前段语言,API设计,网站架构,系统管理,持续集成,服务化,数据处理,并发处理等等,都是相关的知识领域,包括但不限于以下的内容:
- 熟悉Python语言
- 对前端HTML\CSS\JavaScript比较熟悉
- 对网络基础,比如HTTP,TCP/IP等比较熟悉
- 熟悉数据库,缓存,消息队列等技术的使用场景和使用方法
- 日常能使用Linux或Mac系统工作(Windows属于标配)
- 有性能优化经验,能快速定位问题
除此之外,还要对业务有深刻理解,能够写出可维护性足够高的代码。当然,以上都是对经验丰富的开发者而言,对于新手刚入门者,我们朝着这个目标努力学习就好。
下面是基于Python的Web开发技术栈:
五: MVC/MTV介绍
MVC百度百科:全名Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
通俗解释:一种文件的组织和管理形式!不要被缩写吓到了,这其实就是把不同类型的文件放到不同的目录下的一种方法,然后取了一个高大上的名字。当然,它带来的好处有很多,比如前后端分离,松耦合等,就不详细说明了。
模型(model):定义数据库相关的内容,一般放在Models.py文件中。
视图(view):定义HTML等静态网页文件相关,也就是那些HTML,CSS,JS等前端的东西。
控制器(Controller):定义业务逻辑相关,就是我们的主要代码。
MTV:有些WEB框架觉得MVC的字面意思很别扭,就给他改了一下,view不再是HTML相关,而是主业务逻辑了,相当于控制器。HTML被放在Templates中,被称为模板,于是MVC就变成了MTV。这其实是一个文字游戏,和MVC本质上是一样的,换了名字和叫法而已,换汤不换药。
Django的MTV模型组织
目录分开,就必须有机制将他们在内里进行耦合。在Django中urls,orm,static,settings等起着重要的作用。一个典型的业务流程是如下图所示:
一般是用户通过浏览器向我们的服务器发起一个请求(request),这个请求回去访问视图函数,(如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户),视图函数调用模型,模型去数据库查找数据,然后逐渐返回,视图函数把返回的数据填充到模板中,最后返回网页给用户。
我们学习Django学习的是什么?
1,目录结构规范
2,urls路由方式
3,settings配置
4,ORM操作
5,模板渲染
6,其他
Django是一个开放源代码的Web应用框架,由Python写成。
Django遵守BSD版权,初次发布于2015年7月,并于2008年9月发布第一个正式版本1.0.
Django采用了MVC的软件设计模型,即模型M,视图V和控制器C。
Django版本对应的Python版本:
准备知识:请求与相应的处理流程
首先看一个流程图,这是我们访问网站的流程图:
用户在浏览器里输入网址(URL),回车之后就会向目标网址发送一个HTTP请求,服务器收到请求之后就会做出一个响应,把内容通过浏览器渲染出来,呈现给用户看。
下图,就是请求响应的过程:
1,创建Django项目
1.1 使用Pycharm图形化界面创建
这里推荐使用Pycharm,它功能强大,界面友好。
1,点击:file——》new project,出现下面的对话框。
选择Django栏目,输入项目名称,这里采用国际惯例的mysite。选择Python解释器版本,点击create创建。
2,Django将自动生成下面的目录结构:
3,与项目同名的目录中是配置文件,templates目录是html文件存放也就是MTV中T。manage.py是Django项目管理文件。
1.2 使用terminal终端创建
进入指定的项目保存目录,然后运行下面的命令:
1
|
django-admin startproject mysite |
这样就在目录下面生成一个mysite目录,也就是我们的Django项目的根目录。它包含了一系列自动生成的目录和文件,具备各自专有的用途。
注意:在给项目命名的时候必须避开Django和Python的保留关键字,比如“django”,“test”等,否则会引起冲突和莫名的错误。对于mysite的放置位置,不建议放在传统的/var/wwww目录下,它会具有一定的数据暴露危险,因此Django建议你将项目文件放在例如/home/mycode类似的位置。
一个新建的项目结果大概如下(上面已经给出了,在这里再次展示,主要解释目录意义)
1
2
3
4
5
6
7
|
mysite/ manage.py mysite/ __init__.py settings.py urls.py wsgi.py |
各文件和目录解释:
- 外层的mysite目录与Django无关,只是你项目的容器,可以任意命名。
- manage.py:一个命令行工具,用于与Django进行不同方式的交互脚本,非常重要,也是Django的管理主程序。
- 内层的mysite/ 目录是真正的项目文件包裹目录,他的名字是你引用内部文件的包明,例如:mysite.urls。
- mysite/__init__.py : 一个定义包的空文件。
- mysite/settings.py : 项目的主配置文件
- mysite/urls.py : 路由文件,所有的任务都是从这里开始分配,相当于Django驱动站点的内容表格。
- mysite.wsgi.py : 一个基于WSGI的web服务器进入点,提供底层的网络通信功能(通常不用关心)
2,创建APP
在每个Django项目中可以包含多个APP,相当于一个大型项目中的分系统,子模块,功能部件等等,相互之间比较独立,但也有联系。
APP应用和project项目的区别
- 一个APP实现某个功能,比如博客,公共档案数据库或者见到的投票系统
- 一个project是配置文件和多个APP的集合,这里APP组合成整个站点
- 一个project可以包含多个APP
- 一个APP可以属于多个project
所有的APP共享项目资源。
APP的存放位置可以是任何地点,但是通常都将他们放在与manage.py脚本同级的目录下,这样方便导入文件。
在pycharm下面的terminal终端中输入命令(pycharm中没有可以创建APP的图形化按钮,需要在终端中输入命令):
1
|
python manage.py startapp cmdb |
这样就创建了一个叫做cmdb的APP,Django自动生成“cmdb”文件夹。
3,编写路由
路由都在urls文件里面,它将浏览器输入的url映射到相应的业务处理逻辑。
简单的urls编写方法如下图:
4,编写业务处理逻辑
业务处理逻辑都在views.py文件里。
通过上面两个步骤,我们将index这个url指向了views里的index()函数,它接受用户请求,并返回一个“Hello world”字符串
5,运行web服务
现在我们已经可以将web服务运行起来了。
命令行的运行方式为:
1
|
python manage.py runserver 127.0.0.1:8000 |
命令行的展示如下:
但是在Pycharm中,我们可以这样做:
1,在上步工具栏中找到下面图示的图标。
2,点击下拉箭头
3,点击edit Configurations
4,在host中输入:127.0.0.1 port中输入:8000.
5,OK之后,点击绿色的三角,web服务就运行起来了。
6,按图所示,自动跳转到浏览器程序页面。显示的却是下图中的404页面:
,7,修改一下,添加“/index”,就一切OK了
至此,一个最简单的Django编写的web服务器就启动成功了。
6,返回HTML文件
上面我们返回给用户浏览器的是什么?一个字符串!实际上这肯定不行,通常我们都是将HTML文件返回给用户。
1,下面我们写这么一个index.html文件:
2,再修改一下views文件。
3,为了让Django知道我们的HTML文件在哪里,需要修改settings文件的相应内容。但是默认情况下,它正好适用,你无需修改。
接下来,我们可以重新启动web服务。在浏览器刷新一下,你会看到带有样式的“hello world”
注:这里有个小技巧,在多个频繁重启服务时,由于端口未释放的原因,容易启动不了服务,修改一下端口就OK了。
4,结果如下:
7,使用静态文件
我们已经可以将HTML文件返回给用户了,但是还不够,前端三大块,HTML,CSS,JS还有各种插件,他们齐全才是一个完整的页面。在Django中,我们将这些文件统称为“静态文件”,因为这些文件的内容基本是固定不变的,不需要动态生成,一般将静态文件放在static目录中。
对于小项目,这些都不是问题,你可以将静态文件放在任何你的web服务器能够找到的地方。但是对于大型项目,尤其是那些包含多个APP在内的项目,处理那些由APP带来的多套不同的静态文件是个麻烦问题。当然了这也正是django.contrib,staticfiles的用途,它收集每个应用(和任何你指定的地方)的静态文件到一个统一指定的地方,并且易于访问。
7.1,在mysite中新建一个static目录。
你的CSS,JS和各种插件都可以放置在这个目录里。
7.2,为了让Django找到这个目录,依然需要对settings进行配置。
7.3,同样在index.html文件中,可以引入js文件:
7.4,重新启动web服务,刷新浏览器,查看结果。(因为导入js文件,并没有渲染,所以页面不变)
7.5 静态文件的命名空间
与模板类似,我们可以将静态文件直接放在polls/static(而不是创建另外一个polls子目录),但这实际上是一个坏主意。Django将使用它所找到的第一个匹配的静态文件,如果在你的不同应用中存在两个同名的静态文件,Django将无法区别他们。我们需要告诉Django该使用其中的哪一个,最简单的方法就是为他们添加命名空间。也就是说,将这些静态文件放在以他们所在应用的名字同名的另外一个子目录下,也就是多建一层与应用同名的子目录。
PS:良好的目录结构是每个应用都应该创建自己的urls,views,models,templates和static,每个templates包含一个与应用同名的子目录,每个static也包含一个与应用同名的子目录。
7.6 直接访问静态文件
实际上不管是在Django开发服务器上,还是在nginx+uwsgi+django部署的服务器上,都可以通过url访问静态文件,不需要在Django中专门为每个静态文件编写url路由和视图。
8,接受用户发送的数据
上面,我们将一个要素齐全的HTML文件返还给了用户浏览器。但这还不够,因为web服务器和用户之间没有动态交互。
下面我们设计一个表单,让用户输入用户名和密码,提交给index这个url,服务器将接收到这些数据。
1,先修改index.html文件
2,修改views.py文件
3,此时,重启web服务时,会出错,因为Django有一个csrf跨站请求保护机制,我们暂时在settings文件中将其关闭,或者在form表单里添加一个‘{% csrf_token %}' 标签。这里为了演示方便,我们采用临时关闭的方式。
报错页面结果如下:
命令行报错结果如下:
在setting中将其注释,如下:
再次进入浏览器,刷新页面
输入用户名和密码,我们可以在pycharm中看到相应的数据。
9,返回动态页面
我们收到了用户的数据,但返回给用户的依然是个静态页面,通常我们会根据用户的数据,进行处理后再返回给用户。
这时候,Django采用自己的模板语言,类似jinja2,根据提供的数据,替换掉HTML中的相应部分,详细语法以后再学习。
1,先改造views.py文件
2,再改造index.html文件:
3,重启服务,刷新浏览器
可以看到,我们获得了用户实时输入的数据,并将它实时的展示在了用户页面上,这是一个不错的交互过程。
10,使用数据库
流程走到这里,Django的MTV框架基本已经浮出水面了,只剩下最后的额数据库部分了。
上面我们虽然和用户交互的很好,但是没有保留任何数据,页面一旦关闭,或者服务器重启,一切都将回到原点。
使用数据库毫无疑问的,Django通过自带的ORM框架操作数据库,并且自带轻量级的sqlite3数据库,Django默认使用SQLite数据库,因为Python源生支持SQLite数据库,所以我们无需安装任何程序,就可以直接使用,当然,如果我们创建一个实际的项目,可以使用类似PostgreSQL的数据库,避免以后数据库迁移的相关问题,下面我们先看一下。
1,首先是注册app(打开mysite/settings.py配置文件,这是整个Django项目的设置中心):
不注册它,你的数据库就不知道该给哪个APP创建表。
默认情况,INSTALLED_APPS
中会自动包含下列条目,它们都是Django自动生成的:
- django.contrib.admin:admin管理后台站点
- django.contrib.auth:身份认证系统
- django.contrib.contenttypes:内容类型框架
- django.contrib.sessions:会话框架
- django.contrib.messages:消息框架
- django.contrib.staticfiles:静态文件管理框架
2,在settings中,配置数据库相关的参数,如果使用自带的sqlite,不需要修改。
如果你想使用其他的数据库,请先安装相应的数据库操作模块,并将settings文件中DATABASES位置的'default'的键值进行相应的修改,用于连接数据库。
- ENGINE(引擎):可以是django.db.backends.sqlite3,django.db.backends.postgresql,django.db.backends.mysql,django.db.backends.oracle,当然其他的也行。
- NAME(名称):类似MySQL数据库管理系统中用于保存项目内容的数据库的名字。如果你使用的是默认的SQLite,那么数据库将作为一个文件存在你的机器中,此时的NAME应该是这个文件的完整绝对路径,默认值是 os.path.join(BASE_DIR, ’db.sqlite3’) ,将把该文件存储在你的项目目录下。
如果你不是使用默认的SQLite数据库,那么一些诸如USER,PASSWORD和HOST的参数必须手动指定!下面给出一个基于pymysql操作Mysql数据库的例子,更多细节参考此博文。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# mysite/settings.py # Database # https://docs.djangoproject.com/en/1.11/ref/settings/#databases import pymysql # 一定要添加这两行!通过pip install pymysql! pymysql.install_as_MySQLdb() DATABASES = { 'default' : { 'ENGINE' : 'django.db.backends.mysql' , 'NAME' : 'mysite' , 'HOST' : '192.168.1.1' , 'USER' : 'root' , 'PASSWORD' : 'pwd' , 'PORT' : '3306' , } } |
注意:
- 在使用非SQLite的数据库时,请务必预先在数据库管理系统的提示符交互模式下创建数据库,你可以使用命令:“CREATE DATABASE database_name;”。Django不会自动帮你做这一步工作。
- 确保你在settings文件中提供的数据库用户具有创建数据库表的权限,因为在接下来的教程中,我们需要自动创建一个test数据表。(在实际项目中也需要确认这一条要求。)
- 如果你使用的是SQLite,那么你无需做任何预先配置,直接使用就可以了。
在修改settings文件时,请顺便将TIME_ZONE
设置为国内所在的时区Asia/Shanghai
。
同时,请注意settings文件中顶部的INSTALLED_APPS
设置项。它列出了所有的项目中被激活的Django应用(app)。你必须将你自定义的app注册在这里。每个应用可以被多个项目使用,并且可以打包和分发给其他人在他们的项目中使用。
3,编辑models.py,也就是MTV中的M
模型本质上就是数据库表的布局,再附加一些元数据。
Django通过自定义Python类的形式来定义具体的模型,每个模型的物理存在方式就是一个Python的类Class,每个模型代表数据库中的一张表,每个类的实例代表数据表中的一行数据,类中的每个变量代表数据表中的一列字段。Django通过模型,将Python代码和数据库操作结合起来,实现对SQL查询语言的封装。也就是说,你可以不会管理数据库,可以不会SQL语言,你同样能通过Python的代码进行数据库的操作。Django通过ORM对数据库进行操作,奉行代码优先的理念,将Python程序员和数据库管理员进行分工解耦。
这里我们创建了两个字段,分别保存用户的名称和密码
4,我们要在pycharm的teminal中通过命令创建数据库的表,有两条命令,分别是:
1
|
python manage.py makemigrations |
通过运行makemigrations
命令,相当于告诉Django你对模型有改动,并且你想把这些改动保存为一个“迁移(migration)”。
migrations
是Django保存模型修改记录的文件,这些文件保存在磁盘上。在例子中,它就是polls/migrations/0001_initial.py
,你可以打开它看看,里面保存的都是人类可读并且可编辑的内容,方便你随时手动修改。
接下来有一个叫做migrate
的命令将对数据库执行真正的迁移动作。
再输入命令:
1
|
Python manage.py migrate |
migrate命令对所有还未实施的迁移记录进行操作,本质上就是将你对模型的修改体现到数据库中具体的表上面。Django通过一张叫做django_migrations的表,记录并跟踪已经实施的migrate动作,通过对比获得哪些migrations尚未提交。
migrations的功能非常强大,允许你随时修改你的模型,而不需要删除或者新建你的数据库或数据表,在不丢失数据的同时,实时动态更新数据库。我们将在后面的章节对此进行深入的阐述,但是现在,只需要记住修改模型时的操作分三步:
- 在models.py中修改模型;
- 运行
python manage.py makemigrations
为改动创建迁移记录; - 运行
python manage.py migrate
,将操作同步到数据库。
之所以要将创建和实施迁移的动作分成两个命令两步走是因为你也许要通过版本控制系统(例如github,svn)提交你的项目代码,如果没有一个中间过程的保存文件(migrations),那么github如何知道以及记录、同步、实施你所进行过的模型修改动作呢?毕竟,github不和数据库直接打交道,也没法和你本地的数据库通信。但是分开之后,你只需要将你的migration文件(例如上面的0001)上传到github,它就会知道一切。
命令行结果如下:
migrate命令将遍历INSTALLED_APPS
设置中的所有项目,在数据库中创建对应的表,并打印出每一条动作信息。如果你感兴趣,可以在你的数据库命令行下输入:\dt
(PostgreSQL)、 SHOW TABLES;
(MySQL)或 .schema
(SQLite) 来列出 Django 所创建的表。
提示:对于极简主义者,你完全可以在INSTALLED_APPS内注释掉任何或者全部的Django提供的通用应用。这样,migrate也不会再创建对应的数据表。
5,修改views.py中的业务逻辑
重启Web服务后,刷新页面,之后和用户交互的数据都能保存到数据库中,任何时候都可以从数据库中读取数据,展示到页面上。
至此,一个要素齐全,主体框架展示清晰的Django项目完成了。