MVC与MTV模型
MVC百度百科:全名Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
通俗解释:一种文件的组织和管理形式!不要被缩写吓到了,这其实就是把不同类型的文件放到不同的目录下的一种方法,然后取了个高大上的名字。当然,它带来的好处有很多,比如前后端分离,松耦合等等。
MTV: 有些WEB框架觉得MVC的字面意思很别扭,就给它改了一下。view不再是HTML相关,而是主业务逻辑了,相当于控制器。html被放在Templates中,称作模板,于是MVC就变成了MTV。这其实就是一个文字游戏,和MVC本质上是一样的,换了个名字和叫法而已,换汤不换药。
MVC
Web服务器开发领域里著名的MVC模式,将web应用分为以下三层:
模型(Model)
视图(View)
控制器(Controller)
以上三层之间以一种插件式的、松耦合的方式连接在一起:
模型负责业务对象与数据库的映射(ORM)
视图负责与用户的交互(页面)
控制器接受用户的输入调用模型和视图完成用户的请求。
其示意图如下所示:
MTV
Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是指:
1 | M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。 |
除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:
用户通过浏览器向我们的服务器发起一个请求(request),这个请求会去访问视图函数,(如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户),视图函数调用模型,模型去数据库查找数据,然后逐级返回,视图函数把返回的数据填充到模板中,最后返回网页给用户。
Django 的MTV模型组织
Django项目实例
安装
python3.5、pip3及pycharm专业版可自行安装。
例:windows cmd命令行自动安装Pypi提供的最新版本。pip3 install django
配置环境变量
成功安装Djangio后,如有需要,可以将python的Scripts目录加入到系统环境变量中,以便调用django-admin命令。
配置完成后,可直接在cmd任一路径下运行django-admin help命令测试安装和配置完成:
创建django项目和应用
在windows cmd命令行界面下,使用diango提供的命令创建diango项目如下:django-admin startproject mysite
其中mysite是项目名称,可自行替换成你想建立的项目名。
而在该项目下创建应用的命令是:python manage.py startapp blog
其中blog为app,应用名称,可自行替换成你想建立的应用名称。
启动django项目的命令为:python manage.py runserver 8080
runserver 默认为本机(127.0.0.1),后面跟的8080为端口号,可根据实际环境替换。
这样一个简单的原始的django就启动起来了,我们到浏览器输入127.0.0.1:8080实际上访问的就是django的这个项目,如图:
一般开发使用pycharm(IDE)操作是点击file-new project,选择Django栏目;
右侧选择项目所在路径,选择项目使用的python版本环境(可选虚拟环境),
注意Location中选择项目路径的同时所选的目录也就是项目的名称,
More Settings栏可设置模板文件夹名,web应用名称,勾选自动创建相关web应用文件夹等。
点击右下方的Create按钮创建。
Django自动生成类似下面的目录结构:
- 和项目同名的文件夹中存放的是
- settings.py 配置文件;
- urls.py url路由文件;
- wsgi.py 网络通信接口模块;
- templates模板目录下为空,此目录主要用于存放各个html模板文件。
- 项目根目录下的manage.py文件为django项目的管理主程序,工具等。
- 各个应用目录(如我这边的创建的应用名为app01)下存放主要有:
- views.py 为处理业务逻辑;
- tests.py 为单元测试;
- modes.py 为处理数据库;
- 推荐在项目根目录下自行建立起一个static的静态文件,用于存放css,js,img,html等静态文件。
在每个Django项目中可以包含多个APP,相当于一个大型项目中的分系统、子模块、功能部件等等,相互之间比较独立,但也可以有联系。
所有的APP共享项目资源。
编写路由(url控制器)
路由由urls文件进行处理,功能是将浏览器输入的url映射到相应的(views)业务处理逻辑。
由于和业务处理逻辑相关,也就是和views相关,所以在文件开头就需要先导入对应app的views.py文件。
例:没做增添之前的urls.py(包括了官方注释)
1 | """tielemao URL Configuration |
增添路由条目后:
1 | from django.contrib import admin |
编写业务处理逻辑(views视图函数)
urls.py中增添的路由条目中对应了相应的自己命名的业务逻辑函数,
也就是接下来你就需要为此在相应的views.py文件增添上相应的视图函数。
原始的views.py文件:
1 | from django.shortcuts import render |
增添相应函数后:
1 | from django.shortcuts import render |
通过上面两个简单的步骤,将index这个url指向了views里的index()函数,它接收用户请求,并返回一个“hello world”字符串。
我们就可以启动web服务演示一下了。
运行web服务
- 命令行方式:
python manage.py runserver 127.0.0.1:8000 - pycharm中可以通过在工具栏中找到编辑配置文件的选项,快速进行设置host和port后再点击绿色三角形进行运行:
运行效果:
在浏览器中访问http://127.0.0.1:8000
此时会出现404的错误信息,因为此时我们访问的地址并不是index/,在开发过程中,Django给出的这些错误信息很重要,仔细阅读方便排错,但一旦正式上线生产环境,就一定要关掉如此详细的调错信息功能,常见的错误就自己另写html报错页面。
在地址栏中输入http://127.0.0.1:8000/index/,访问才会出现己设置好的正常显示的hello world!
返回HTML
上面例子返回给用户的是一个字符串,真正的web应用肯定是不会这样做的,通常返回的都应该是一个HTML文件给用户。那么,我们写如下showtime函数和time.html的HTML文件,做为一个用户访问获取
当前时间的功能例子:
- urls.py代码如下:
1 | from django.contrib import admin |
- views.py代码如下,增加一个showtime函数:
1 | from django.shortcuts import render |
request,它是一个对象。
当中存储了请求信息,比如请求路径,请求方式,GET数据,POST数据…等等。
必须要接收一个request参数。
当你想返回一个html文件时,不是使用HttpResponse方法,而是使用render方法来渲染(打包)。
不过本质上render最终还是使用了HttpResponse方法发送byte字节给浏览器的。
- 模板templates目录下,新建一个time.html:
1 |
|
访问效果如下:
settings.py设置模板文件夹
settings.py文件中有TEMPLATES变量,它是一个列表,列表中又存放了一个字典,其中一个键值对'DIRS':[os.path.join(BASE_DIR, 'templates')]
效果就是默认设置了模板目录是使用默认的项目文件夹下的templates目录。
如果有特殊需要修改的就是在此改动。
另外django有一个好处,代码更改之后,一般无需重启web服务,它会自动加载最新代码。
1 | TEMPLATES = [ |
使用静态文件
将html文件返回给用户还不够,前端三大块,HTML、CSS、JS还有各种插件等,完整齐全才是一个好看的页面。在django中,一般将静态文件放在static目录中。接下来,在项目根目录下新建一个static目录。
同时,我还在此目录下建立起js,css,img子目录和相关文件,如图:
static这个静态目录名和Django默认设置的静态目录名别名一致,
在settings.py中可找到相关设置项,就是在结尾处再添加上新的一行表示告诉Django静态目录的路径:
1 | # Static files (CSS, JavaScript, Images) |
同理,在html文件中引用静态文件,例如jquery.js文件如下:
1 | <!DOCTYPE html> |
主要看<script src="/static/js/jquery.js"></script>这一行,里面的路径并没有写死,而是使用了static/来代指了真实的静态目录。
接收用户发送的数据(get和post请求)
至此,我们做到了将一个要素齐全的HTML文件返还给了用户浏览器。
但这还不够,因为web服务器和用户之间还没有动态交互。
下面我们来设计一个login页面,上面建立一个表单,让用户输入用户名和密码,提交给login
这个url,服务器将接收到这些数据。
login.html
1 |
|
这其中牵涉到一个csrf的防护机制
CSRF百度百科:CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
假如没有加这一行防护,运行时将会报如下图的错误:
urls.py中urlpatterns添加路由条目:path('login/', views.login),
views.py中添加login函数:
1 | def login(request): |
此逻辑处理将会在pycharm中可以看到用户输入的用户名密码。
运行效果如下:
html页面效果:
pycharm后端效果:
pycharm中可以看到提交后的post请求数据后端都获取到了。
返回动态页面
我们收到了用户的数据,但返回给用户的依然是个静态页面,通常页面会根据用户的数据,进行处理后在返回给用户。
django采用自己的模板语言,类似jinja2,可根据提供的数据,替换掉HTML中的相应部分。
例:views.py文件修改如下:
1 | # 创建一个用户信息表,预设了两个数据,将返回给浏览器展示给用户 |
而login.html相应修改:
1 |
|
login.html中利用for循环将data(引用)迭代填入数据到表格。
访问页面并输入一些数据测试效果如下:
效果就是用户列表会随着提交的数据而发生变化,算是一个简单的动态页面, 和用户的交户过程。
使用数据库
Django默认使用的是Sqlite,要使用mysql的话需要修改以下配置
修改settings.py文件
1 | DATABASES = { |
1 | # 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替 |