关于框架的纷乱战争,已经打响了数年。当我们撇去所有夸张的修饰和浮华的外表,我们发现隐秘于框架中的血淋淋构造,我们也发现了许多不曾留意的思想。当我们从单细胞的生命体进化到如此精密的高等动物之后,往往就会沉迷于更复杂、更神秘和更无法理解的科学的漩涡中。
现在,让我们抛弃所有的浮躁和喧哗,回归本该自然的思想——简。
聪明的故人们早已明白此理,我们追崇的不应该是漂浮于繁华之上的繁杂,当返璞归真的时候,才发现最简单的方法才是构造万丈建筑的基石。
基于MVC的开发模式早已被业界作为了开发的默认值, Django也是秉承于MVC模型,但它发散出的思想足以让你倾心。
Django为何物首先,你要注意,Django不仅仅是一个著名的爵士乐吉他演奏家 Django Reinhardt的名字。因为个人爱好,框架开发者以Django命名整个项目。
Django是一个具有高度抽象的开源web开发框架,底层基于Python语言构建,因为Python的简明、干净、优雅和高级,注定Django成为一个成功高效的web框架。
在Django之前,注意一点,Django基于MVC开发模型,但它并不完全遵循MVC的开发模式!在Django的思想中,我们管它叫MTV开发模式。注意,不要理解成“Music Television音乐电视”,它的实际意思是Mode+Template+View,对了,你应该能够明白它的意义了:模型+视图+模板。你可能又在想了,Django不用Control吗?当然需要,所以,我们这里的View严格意义上来讲应该是“视图控制器”。在这里可能无数陷入MVC的英雄好汉始终觉得不妥,这样的区分是否正确?暂且不管命名是否科学,从现在起,请抛开所有关于MVC的东西,静静的,接受MTV的哲学吧!
从哪里开始现在正式开始Django之旅。
Django是基于Python语言的,所以你的计算机一定要有Python环境,在Python官方网站中下载Python的安装文件,然后设置环境变量:新建一个变量:PythonHome;变量值:你的python安装路径。下面在Path变量中添加一个值:%PythonHome%;(可不要忽略了还有个分号)。安装成功后就完成了Django的基础设施建设。
Django的官方网站/可以下载到最新版本的Django。解压Django-1.0.tar.gz,在DOS环境下进入Django-1.0.tar.gz解压目录,键入一下命令:
Python setup.py install
后回车,安装完成后请回滚鼠标检查安装信息,如果没有提示错误信息则安装正确,警告信息则可忽略。
就这样,你的Django就安装完成了,太快了还没回过神?没事,我们再回味下,当我们键入Python setup.py install以后发生了什么呢?原来,他将Django所需的库文件copy到了python的安装目录下,当你打开目录:
‘python安装目录’/Lib/site-packages
后就会惊奇的发现,出现了一个‘django’文件夹,它就是你所需的技术提供者。
就是这么神奇,我们已经完成了Django所需的所有内容,下面需要做的,就等你向这个框架里添砖加瓦了。
首先我们创建一个Django项目,才能谈MTV的内容。
Step1. 在DOS模式下进入你习惯的工作目录,如 Earth/(毕竟我还是比较喜欢在地球上工作)。
Step2. 运行命令:django-admin.py startproject cube。其中“cube”是我们整个项目的名字,当然可以随你的意愿取名。再回到Earth目录下,Django就为我们创建好了一个项目,名字叫做“cube”,进入目录看看发生了什么。
奇怪,怎么文件夹内会有文件呢?这就是Django!为我们省去了许多事,比如创建千篇一律的文件,而其他无关的事情就不会替你干了,比如替你做饭。让我们看看这几个文件:
__init__.pymanage.py settings.py urls.py
熟悉Python的程序员就会了解__init__.py是什么,它会告诉Python解释器,这个目录是一组模块(module),仅此而已。manage.py是一种命令行工具,可让你以多种方式与该 Django 项目进行交互,比如在DOS下向Django命令:快去扫地!settings.py里面存储着该 Django 项目的设置或配置,如同java或其他web项目的config文件。urls.py是Django 项目的 URL 声明文件,它是Django所支撑站点的内容列表,完成整个项目以后,你就会发现此文件的重要程度远大于你的显示屏幕。
Step3. 我们的帝国大厦框架已经搭建完成,下面我们开始设计第一层!创建一个app!什么是app呢?这个问题会引起一些疑惑,我们可以认为app是一个功能集,如在一个大型项目里的登陆功能,我们可以把它看作一个app,我们的Django项目即是由若干app组成的。在DOS下进入工作目录“cube”,键入命名让Django为我们完成剩下的事情:
python manage.py startapp ChengduCube
好了,我们创建了一个ChengduCube的app,进去看看Django又为我们完成了什么(我老是希望Django为我完成更多的事情,它也从没让我失望)。是的,他又为我们创建了3个文件:
__init__.py models.pyviews.py
又看到__init__.py文件了,没错,他仅仅是告诉Python,这是一个module!而其余2个文件我们在后面会一一讲述的。
看看我们做了哪些事情吧,奇怪,感觉上我们完成了如此多的工作,但实际情况是:我居然只输入了2个命令!太神奇了。
看看我们的成果吧,DOS下切换到cube目录,再次向Django发出命名:
python manage.py runserver
此命名告诉Django:快启动服务器!我要运行了!当你发现屏幕中出现:
0 errors found.Django version 1.0, using settings 'cube.settings'Development server is running at http://127.0.0.1:8000/
恭喜你,你可以开始了。
从Model开始延伸
我们已经搭建好了整个大楼的模样,第一层楼的框架也已经建立好了,我们就可以做“真正”的开发了(其实前面已经进入了真正的开发,只是Django帮了很大的忙)。
这节从Model说起,前面我们创建“ChengduCube”app不是Django自动为我们创建了3个文件吗?其中一个是models.py。这个文件就是我们这个app中的Model,我们会把所有此模块能涉及到的实体模型都定义在models.py文件里。如果我们做Struts,我们会为每个Model创建一个类文件,而且会配置一大堆xml的配置文件,同样的情况当然不会出现在Django中,在Python哲学的第一条则准则是简单之上。我们会把所有的模型都定义在Model中,而且几乎不需要做多余的配置,让Django帮你完成剩下的事情吧,趁这个时候你可以喝杯茶。
从何处得知这个类是一个Model呢?用继承机制实现吧。
Step1. 导入Django的models模块:
from django.db import models
Step2. 建立模型类,当然,有多少实体模型就可以创建多少类。
class people(models.Model):
Step3. 添加字段。注意,这里我说的是字段,不是属性,你一定会笑“难道他们不是一个意思吗?“。我想说的是,名字的说法不重要,但是命名往往会影响我们对某个事物的主观判断,这里我命名为字段,是要让我们时刻注意:这是数据库!
对,我们可以将Model就看作是数据库,应为Django的ORM模型会为我们做其余的事情,实际上的数据库服务器对我们来说是透明的。
其次,对于设计数据库来说,先建立数据库表的数据结构还是建立实体类的数据模型,始终是个纠结不清的问题,从面向对象编程来讲,我们推荐后则,这也是我将“属性”命名为字段的原因之一。
Step3. 实体模型写好,接下来制作数据库操作对象(你该不会想直接用Model操作数据库吧,虽然可行)。
现在,我们终于可以亲手创建一个新文件了,太好了,至少说明这个程序是由我亲力亲为的!新建一个文件Group.py,导入下面的模块:
from cube.apps.ChengduCube.models import people
下面的代码我稍作解释(请不要纠结于多余的代码,仅需关注一种某些语句即可):
class Group(object):def search(self,start=-1,limit=0,order_by=None,*args,**kwargs):map = {}order = '-create_time'if order_by:order = order_bygroups = people.objects.filter(*args,**kwargs).order_by(order)map['count'] = groups.count()if start>=0 and limit>0:groups = groups[start:start+limit]map['records'] = groupsreturn map
是的,这里我写了一个函数:search(),你仅需关注people.objects.filter(),就足以满足你的求知欲,因为就是这句话,Django的ORM帮我们完成了足够多的事任务,比如说查找所有的的people“数据表”内容,并加以过滤。
这就是不可思议的Django ORM!如此简单,更不需要多余的配置!
关于Model的剩余问题,具体怎么添加字段,Mata内部类的作用,操作数据类对象的实现(增删改查)等,请读者在
/了解更多,毕竟文的真正意义不在于讲述Django的语法,我想说的是,框架本应该很简单,Django便是如此令人心情愉快。
View非“视图”
现在我们讨论下在MTV模型中最让人琢磨不透的问题——V到底是什么。
显然,View是指视图,但在Django中的视图和大宗MVC模型下的视图又有明显的区别。对于用户来说的View在Django中的真正控制者是Template, 对于Django服务器来讲,View就是让服务器“看到”的界面,所以,在前文中我已经说明过,暂且抛弃他的名字,我们以后就将View解释成:视图控制器!是的,其实他的作用是就仅仅是Control and Control。
创建View,我们需要做什么呢?
前面建立app时,Django帮我们创建好了一个view.py,还记得吗?是的,只需修改它,就大功告成。
Step1. 导入相关的模块和函数。
Step2. 写个处理请求的方法:
from django.http import HttpResponse//处理http相应的函数from django.shortcuts import render_to_response//模板加载的函数from board.models import people //people还记吧?对!这是我们的Modeldef index(request): //处理请求的方法,命名为index
request参数不能少,一个http请求会直接用这个方法来处理,所以这个参数是必需的。
你可能又会疑惑了,Django怎么知道我的请求是交给那个方法来处理呢?是啊,我们是在写程序,不是在使用AI,所以当然需要配置文件来管理这件事。还记得前面创建Django项目的时候系统为我们创建好的url.py吧,对,就是这个文件来当此大任。
Step3. 当我们所有的业务逻辑处理完成后,会选择一个模板来展现结果。类似于java里的RequestDispatcher对象(仅仅是为了说明理解罢了,实际情况是“完全不类似”),Django也会有自己的解决方案,render_to_response(‘index.html’,{‘cube’:myCube})函数会加载一个名叫index.html的模板,接着传递一个值为myCube对象的参数cube(当然,因为这里是字典数据结构,你可以传入任何个数的参数,只要能在模板上用到)。
好了,现在我们只需要了解这么多,最后我们梳理过程的时候会让你醍醐灌顶般恍然大悟。
渲染Template
太好了,终于到Template了,这里我们只需要知道很少的内容就征服Template。
Step1. 熟悉HTML代码(在这里强调这个问题似乎有些多余)。
Step2. 你知道{{…….}}和{%.......%}的区别吗?依然用jsp做类比,前者类似于<%=…….%>,后者则类似于<%.......%>,现在明白了吧。
但我依然要不厌其烦的提醒一点,我们上面做的仅仅是“类比”,应为很多事物的实际情况是有出入的,比如在{{……}}里是写Python代码吗?答案可能另你失望:不是!在{{……}}里的内容是有一定规范的,不是任何Python语句都能写入,或则说根本就不能写Python语句,里面的内容是“Template语言”。
什么?又要学习一门新语言?
放心,这里所谓的“语言”,仅仅为了说明不能把{{….}}和<%......%>混为一谈。{{….}}里输入Template的特定标识符,这些语句简单到任何人都能够理解,如{%if people%},{%endif%}之类。
在制作好精美的页面后,在需要动态绑定数据的块或逻辑处理的地方,加入{{…}}或{%....%}就完成了,例如,
<h1>{{cube}}</h1>,还记得上面的render_to_response()传入的参数吧,就在此时发挥作用了。
是的,就“像”jsp一样。
现在开始MTV正如你看到的,我们已经将MTV的三大模块都完成了,接下来我们来组装它吧,就像戴高乐积木一样。
我们首先做什么呢?配置urls.py和setting.py,然后呢?还有然后吗?不必了,仅仅这样就足够了。下面我们先来看看urls.py的秘密。
urlpatterns = patterns('',(r'^cube/', 'cube.foo.index),)
天啊,这就是urls.py文件的全部吗?是的,仅此而已。
在Django中,urls.py文件是用来匹配http请求url和对应处理函数的匹配文件,正如你所看到的,patterns()函数里是数组,数组的元素嵌套另一个数组,在嵌套数组里定义我们的匹配规则,上例中,第一个元素是请求的url匹配,第二个元素是对应的处理函数,正如我们在view里写的一样。最前面的r表示‘….’里的字符串应该用正则表达式匹配。
Django中的url是优雅的,所以,请摒弃:
/index.jsp?type=news&year=&month=3&day=30/
优雅的url,是需要精进设计的:
/index//3/30
这显然是CubeTech公司在-3-30的新闻。
Setting.py文件则是Django项目的核心文件,很多系统级的配置都要靠它完成,先看看Setting.py里都有些什么吧。
DATABASE_ENGINE = 'mysql'//数据库引擎,如'mysql', 'sqlite3' or 'oracle'DATABASE_NAME = 'cube' //数据库命名DATABASE_USER = 'test' //用户DATABASE_PASSWORD = '0987654321' // 帐户密码DATABASE_HOST = '127.0.0.1' // 数据库服务器ipINSTALLED_APPS = (‘cube’,) //这个属性是配置你系统需要的app,想起来了吗?cube,就是我们创建的第一个模块。 TEMPLATE_DIRS = () //模板文件目录所在地,将你模板文件夹地址写在这里就可以了。
简单配置,就到这里了,我们完成了!不可思议的,Django居然为我们完成大部分内容,甚至你可能还没发觉。
下面,让我作为一个http请求的数据包,带你进入真正Django的神奇——MTV模型的协同。
当用户在浏览器地址栏输入/cube时,我被成功发送到了服务器。
服务器开始工作!
首先查找urls.py,正则表达式没匹配到相应的url?那就直接返回500错误到了用户,流程结束。能够匹配?好的,找到对应的函数(即view里写的index),流程进入了index函数,接着便是对我进行惨无人道处理工作,比如,克隆我的干细胞,然后被一个叫做Model的判官流放到一个叫做“mysql”的地方。
在所谓的业务逻辑完成以后,开始渲染模板,render_to_response()方法起作用了,它将http请求转发到了相应的模板页面,然后就可以显示出来了。哈哈,你一定是这样想的吧!
错!
Django中的渲染模板,从命名的角度上其实已经说明白了,既然是渲染模板,那模板一定是处于被动状态的,一定是什么东西来渲染它吧,它是什么呢?就是View!
是的,我们可以这样去理解他:render_to_response()函数将模板以字符串的形似流进view处理函数里,然后每逢{{….}}或{%....%}的时候就用参数里的对象去代替,就这样,我们就渲染出来一个模板了。
现在我处于展示层,当模板渲染完毕,Django服务器就会像客户端返回请求响应,于是,将view函数渲染的效果返回给客户,注意一点,其实你看到的url依然是view,不是Template!
祝贺你,你已经了解了MTV的全部。
哲学不止于此
Django的主要目的是简便、快速的开发数据库驱动的网站。
Django让你很轻松的做“对”事情。
现实世界的复杂性让我们心力交瘁,万事万物皆由简构成。世上没有巨大无比的问题,只有当忽视身边的细小错误以成为一种习惯,巨大的问题就铺天盖地的袭来了。无数真实世界的问题交织起来,为了解决这些问题,Django才开始筹划起来。不是为了在开发框架中占有一席之地,仅仅是想要去解决问题,去解决真正需要Django处理的问题。
什么语言,什么框架,都不是最重要的,当我们能迎合用户的需求,快速的作出反映和调整,才是团队中应有的品质。计算机永永远远都仅仅是个工具,思想的力量远比一个工具强大得多。
CubeTech
刘言Zane