第四章 Django的MVC框架

4.1 Django的MVC框架简介

MVC是一种软件工程设计方法,它把一个要创建的系统分成三部分,分别是Model数据模块,View视图模块以及Controller控制模块。

Model数据模块:包含系统中的数据内容,通常以数据库的形式来存储,如果这些内容有变动,就会通知View实时更改显示的内容,一些处理数据的程序逻辑也会放在这里。

View视图模块:创建和用户之间的界面,把用户的请求传送给Controller,并按照Controller的要求把来自Model的数据显示出来。

Controller控制模块:派发View传来的用户请求,并按照这些请求处理数据内容以及设置要显示的数据。

好处:大幅地降低系统的复杂性。

Django主要的架构形成了使用Model、Template和View三部分的搭配。这三部分分别对应网站的数据存储model.py、网站的模板文件组(一般放在templates文件夹下的html文件)以及控制如何处理数据程序逻辑的views.py,其中许多控制逻辑也被放在整个Django Framework中,(如urls.py的设置等)。

在此架构下,初学者可以这样看:使用templates来做每个网页的外观框架,送至templates中要被使用的数据尽量是可以直接显示的简单形式。
如果需要对变量进行更复杂的运算,那么这些工作应该放在view.py中完成。

在models.py中定义所有需要用到的数据格式,一般是以数据库的形式来存储的,定义后的Model数据类要把它import到views.py中

主要的操作流程为:用户在浏览器下达request,这个request会先被送到网站服务器中做分派的工作,这个分派的工作指定在urls.py中完成。每一个分派的工作都被设置成views.py中的函数,也就是主要处理数据的逻辑,在views.py中完成。因此所有在urls.py中指派的函数要在urls.py的前面import才行。

在Django MTV架构下的网站开发步骤

  • 需求分析,列出本次网站项目所要实现的目标,包括简单的草图,与功能方块图。
  • 数据库设计,网站中所有会用到的数据内容、格式、以及各个数据之间的关系。减少开始设计程序后修改Model的工作。
  • 了解网站的每一个界面,并设计网页模板(.html)文件
  • 生成项目,创建APP
  • 创建templates文件夹,并把所有网页模板(.html)文件都放在此文件夹
  • 创建static文件夹,并把所有静态文件(图像文件、CSS文件、.JS文件等)都都放在此文件夹中
  • 修改setting.py,把相关文件夹设置都加入,也把生成的app名称加入INSTALLEC_APPS序列中
  • 编辑models.py创建数据表格
  • 编辑views.py先import在models.py中创建的数据模型
  • 编辑admin.py把models.py中定义的数据模型加入,并使用admin.site.register注册新增的类,让admin界面可以处理数据库内容
  • 编辑views.py设计处理数据的相关模块,输入和输出都通过templates相关的模块操作获取来自于网页的输入数据,以及显示.html文件的网页内容
  • 编辑urls.py先import在views.py中定义的模块,创建网址和views.py中定义的模块的对应关系
  • 执行python manage.py makemigration; python manage.py migrate; python manage.py runserver测试网站

4.2 Model简介

首先创建项目:

django-admin startproject mysite
cd mysite/
python manage.py startapp myapp

Model是Django表示数据的模式,以Python的类为基础在models.py中设置数据项与数据格式。基本上每个类对应一个数据库中的数据表。因此,定义每个数据项时,除了数据项名称外,还要定义此项目的格式以及这张表格和其他表格相互之间的关系(即数据关联)。网站的其他数据就可以使用Python语句来操作这些数据内容,而不用关心实际使用的SQL指令。

例:

from django.db import models
class Post(models.Model)title = models.CharField(max_length=200)slug = models.CharField(max_length=200)body = models.TextField()pub_date = models.DateTimeField(default=timezone.now)

在参数中应该导入models.Model,然后就可以使用models.* 来指定数据表中的每一个字段的特征。

常用的数据字段类型:

  • CharField(max_length)——用来存储较短数据的字符串,通常使用于单行的文字数据
  • DateField(auto_now)——每次对象被存储时就自动加入当前日期。日期格式可用于datetime.date
  • TextField——长文字格式,一般用在HTML窗体的Textarea输入项目中

首次设置Model的内容要先执行python manage.py makemigrations以及python manage.py migrate

然后系统就会把我们设置的NewTable数据表建立到数据库中,默认是SQLite,也就是存在于同一文件夹下的db.sqlites文件。

会看到0001_initial.py以及__init__.py这两个文件。0001文件就是记录第一次Model设置的数据表内容,因为一开始只有一个设置,所以只有0001这个版本。Django偷偷帮我们加上了一个id字段,设置为主键,并自动增加了数值内容,以便它内部的数据管理。

在admin.py中创建数据表管理界面

在models.py中创建类之后,只要在admin.py中加入这个NewTable,就可以在/admin中管理这张表了(事先要createsuperuser创建管理员账号和密码)

先创建一个产品类(models.py):

class Product(models.Model):SIZES = (('S', 'Smaill'),('M', 'Medium'),('L', 'Large'),)sku = models.CharField(max_length=5)name = models.CharField(max_length=20)price = models.PostitiveIntegerField()size = models.CharField(max_length=1, choices=SIZES)

上述代码,先创建一个名为SIZE的元组,其中每个元素也是一个元组,第一个项目是要被实际存储的内容,此例为’S’,’M’,’L’,后面那个项目是对应的说明,此例为’Smaill’等。编辑models.py后一定要执行migrate才行(如果中间修改过,就需要先执行makemigrations,这两个指令简单地看就是要求套用最新的数据表的新增或修改的内容)。执行:

python manage.py migrate

回到admin.py,加入这个新的类并注册:

from django.contrib import admin
from myapp.models import Productadmin.site.register(Product)

如何修改数据库

首先需要在models.py中修改,之后需要执行makemigrations以及migrate记录下这个修改操作。

这些操作都会被记录在myapp/migration文件夹下,分别是:

ls myapp/migrations/
0001_initial.py   0002_auto_20170815_0643.py   __init__.py
0001_initial.pyc  0002_auto_20170815_0643.pyc  __init__.pyc

注:0001是建立了Project这个数据表,0002是修改small的程序。

在Python Shell中操作数据库

在python中一般不使用SQL指令来存储数据,而是以ORM的方式来存取数据库里的内容。它以对象的的方式来看待每一条数据,可以解决底层数据库兼容的问题。如果把这些指令对应到实际每一种数据库的内部操作,就由元数据以及Django内部去处理,开发网站的文员不用去担心这个部分。

python manage.py shell
from myapp.models import Project
p = Product.objects.create(sku=0001,name='GrayBox',price=100,size='S')
p.save()

过程:python manage.py shell 是进入拥有此网站环境的Python Shell,一开始要导入在models.py中建立的Product数据表。通过Product.object.create指令创建一组数据,同时把这组数据交给一个变量(此例为p),然后通过p.save()把它真正存到数据表中。离开后,在admin界面中,即可查询到此记录。

使用Product.objects.all()函数可以取得所有数据(按顺序保存在一个数组中)操作过程:

allp = Product.objects.all()
allp[0]

在class Product中加入如下函数,解决显示不明确的项目标题:

def __unicode__(self):return self.name

这个函数是在这个类的实例被打印出来的时候会被调用,直接显示其中的name字段。

数据的查询与编辑

Django的ORM操作最重要的是找到数据项(记录),把它放到某个变量中,然后就可以针对这个变量做任何想要的操作,包括修改其中的内容,只要最后调用了save()函数,修改的内容,就会反映到数据库。

4.3 View简介

View是Django最重要的程序逻辑所在的地方,网站大部分程序设计都放在此。这里放了许多我们要操作的数据,以及安排哪些数据需要被显示出来的函数。在函数中把这些数据传送给网页服务器或交给Template的渲染器,再发送到网页服务器中。这些放在views.py中的函数,再由urls.py中的设计进行对应和派发。

要直接显示数据到网页,最简单的步骤是:先到urls.py设置一个网址的对应,然后在views.py中编写一个函数,通过HttpResponse传送出想要显示的数据。

如果想要建立一个简单显示个人信息的网页,这个网页希望放在/about路径中,那么可以在views.py中编写一个about函数,语句如下:

from django.http import HttpResponse
# Create your views here.def about(request):html = '''
<!DOCTYPE html>
<html>
<head><title>About Myself</title></head>
<body>
<h2>Min-Huang Ho</h2>
<hr>
<p>
Hi, I am Min-Huang HO. Nice to meet you!
</p>
</body>
</html>
'''return HttpResponse(html)

在views.py最前面,导入用来处理HTTP协议的模块,about()函数需要接收request参数。Python中三引号来定义html字符串,这样可以使用多行的HTML程序代码,排版上较方便。然后通过HttpResponse(html)传送出去。

然后修改urls.py来设置:

from django.conf.urls import include, url
from django.contrib import admin
from myapp.views import abouturlpatterns = [url(r'^admin/', include(admin.site.urls)),url(r'^about/', about)
]

在views.py中显示查询数据列表

下面要在views.py中查询models.py中定义且已存储的数据。并显示在用户端的网页上。

在views.py中要建立一个函数,此例中为listing

#_*_ coding: utf-8 _*_
from django.shortcuts import render
from django.http import HttpResponse
from myapp.models import Product
# Create your views here.def listing(request):html = '''
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>手机列表</title>
</head>
<body>
<h2>以下是本店手机销售列表</h2>
<hr>
<table width=400 border=1 bgcolor='#ccffcc'>
{}
</table>
</body>
</html>
'''products = Product.objects.all()tags = '<tr><td>产品</td><td>售价</td><td>型号</td></tr>'for p in products:tags = tags + '<tr><td>{}</td>'.format(p.name)tags = tags + '<td>{}</td>'.format(p.price)tags = tags + '<td>{}</td></tr>'.format(p.size)return HttpResponse(html.format(tags))

这里设计了一个<table>{}</table>设计,即从数据库’捞’数据,表格中的实际内容是在后面的程序代码中准备好以后,再以format函数把它安插在”{}”中,因此要先放一个大括号留着后面使用。

Product.objects.all()找出所有数据项并存放在peoducts变量红,而以tags变量来把HTML表格的标记和数据排版在一起,在函数最后使用html.format(tags)把表格的内容放在html字符串正确的地方,再由HttpResponse函数返回给网页服务器。

在urls.py中也要加入listing函数,以及import包。

from django.conf.urls import include, url
from django.contrib import admin
from myapp.views import about,listingurlpatterns = [url(r'^admin/', include(admin.site.urls)),url(r'^about/', about),url(r'^list/', listing),
]

访问0.0.0.0:8000/list 即可显示数据列表

网址栏参数处理的方式

如果要显示某个指定的机型,应该如何处理?

  • 第一点:是在views.py中设置的处理函数必须能够接收参数,根据参数寻找所需的数据并加以显示
  • 第二点:在urls.py中的网址对应出也要有能力传送参数到views.py中

首先设计一个处理函数disp_detail()

#_*_ coding: utf-8 _*_
from django.shortcuts import render
from django.http import HttpResponse,Http404
from myapp.models import Product
# Create your views here.def disp_detail(request, sku):html = '''
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>{}</title>
</head>
<body>
<h2>{}</h2>
<hr>
<table width=400 border=1 bgcolor='#ccffcc'>
{}
</table>
<a href='/list'>返回列表</a>
</body>
</html>
'''try:p = Product.objects.get(sku=sku)except Product.DoesNotExist:raise Http404('找不到指定的产品编号')tags = '<tr><td>产品编号</td><td>{}</td></tr>'.format(p.sku)tags = tags + '<tr><td>{}</td>'.format(p.name)tags = tags + '<td>{}</td>'.format(p.price)tags = tags + '<td>{}</td></tr>'.format(p.size)return HttpResponse(html.format(p.name, p.name, tags))

首先在import的地方多导入了Http404,用来产生标准的”404找不到网页”
的响应,当发生找不到数据的情况时(函数中的except Product.DoesNotExist例外处理),只要使用raise Http404(‘要显示的信息’)就可以了。

另外在disp_detail(request,sku)后面多加一个传送进来的参数sku(数据表中的产品编号),通过这个sku号,使用Product.objects.get(sku=sku)来搜索数据。如果找不到就产生一个Http404的例外;如果找到了。就把数据放在P变量中,然后可以在后面取出应用。

更改urls.py:

from django.conf.urls import include, url
from django.contrib import admin
from myapp.views import about, listing, disp_detailurlpatterns = [url(r'^admin/', include(admin.site.urls)),url(r'^about/', about),url(r'^list/([0-9a-zA-Z]+)/$', disp_detail),url(r'^list/', listing),
]

访问 0.0.0.0:8000/list/2/

4.4 Template 简介

要建立专业网站,一定要使用高级功能的模板网页显示方法。也就是把HTML文件另外存成模板文件,然后把要显示在网页的数据另外以变量的方式传送给渲染器,让渲染器根据变量的内容和指定的模板文件进行整合,再把结果输出给网页服务器。

创建template文件夹和文件

首先在当前的项目目录下创建一个名为templates的文件夹,它的等级与manage.py属同一层。接着在settings.py中设置TEMPLATES,如下:

TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [os.path.join(BASE_DIR, 'templates')],

接着在templates文件夹中创建一个about.html文件,如下:

<!-- about.html -->
<!DOCTYPE html>
<html>
<head><meat charset='utf-8'><title>About Myself</title>
</head>
<body>
<h2>Zhe-Rui Chang</h2>
<hr>
<p>
Hi, I am Zhe-Rui Chang.Nice to meet you!
</p>
<em>今日佳句:{{ quote }}</em>
</body>
</html>

这里把quote变量放在”{{}}”中,即可在网页打开时显示出来。

传送变量到template文件中

在views.py前面要使用import get_template模块,还用到了随机数功能:

#_*_ coding: utf-8 _*_
from django.shortcuts import render
from django.http import HttpResponse,Http404
from myapp.models import Product
from django.template.loader import get_template
import randomdef about(request):template = get_template('about.html')quotes = ['今日事,今日毕','要收获,先付出','知识就是力量','一个人的个性就是他的命运']html = template.render({'quote':random.choice(quotes)})return HttpResponse(html)

在程序中,首先使用get_template函数取得about.html文件的执行实例,然后用template.render()方法函数执行网页显示的工作。此例中,要显示quote变量,因此会在render函数中传送“{‘quote’:random.choice(quotes)}”参数进去,因此在about.html中就可以顺利取得quote变量,并把它显示出来。渲染后的网页数据放在html变量中,再使用HttpResponse函数把它传给网页服务器。

同样的方法也可以用到disp_detail函数中,创建一个disp.html

<!-- disp.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>{{product.name}}</title>
</head>
<body>
<h2>{{product.name}}</h2>
<hr>
<table width=400 border=1 bgcolor='#ccffcc'>
<tr><td>产品编号</td><td>{{product.sku}}</td></tr>
<tr><td>产品名称</td><td>{{product.name}}</td></tr>
<tr><td>售价</td><td>{{product.price}}</td></tr>
<tr><td>产品型号</td><td>{{product.size}}</td></tr>
</table>
<a href='/list'>返回列表</a>
</body>
</html>

view.py:

#_*_ coding: utf-8 _*_
from django.shortcuts import render
from django.http import HttpResponse,Http404
from myapp.models import Product
from django.template.loader import get_template
import random
# Create your views here.def disp_detail(request, sku):try:p = Product.objects.get(sku=sku)except Product.DoesNotExist:raise Http404('找不到指定的产品编号')template = get_template('disp.html')html = template.render({'product':p})return HttpResponse(html)

render在渲染时会把变量中的内容当作一般的字符来处理,而不是HTML标记,因此不应该在view.py中处理网页呈现的问题,应该回归到template文件中才对。因此,我们要做的是把变量传到disp.html中,然后在disp.html中以template的命令来处理。

在template中处理列表变量

view.py

def listing(request): products = Product.objects.all()template = get_template('list.html')html = template.render({'products':products})return HttpResponse(html)

把找到的products列表变量直接放到template中就可以了,真正显示内容的格式则放在list.html中执行。

list.html

手机列表

以下是销售中的手机列表


{% for p in products %}

{% endfor %}

产品名 售价 型号
{{p.name}} {{p.price}} {{p.size}}

for循环时,会逐一把product列表中的每一个元素取出来放在p中。

4.5 最终版本

为网站加入首页,index.html(之前在about.html的数据改至此)

index.html

<!-- index.html -->
<!DOCTYPE html>
<html>
<head><meat charset='utf-8'><title>Welcome to mynewsite</title>
</head>
<body>
<h2>Welcome to mynewsite</h2>
<hr>
<ul><li><a href='/list'>手机列表</a></li><li><a href='/about'>关于我</a></li>
</ul>
<hr>
<em>今日佳句:{{ quote }}</em>
</body>
</html>

urls.py

from django.conf.urls import include, url
from django.contrib import admin
from myapp.views import about, listing, disp_detail, indexurlpatterns = [url(r'^admin/', include(admin.site.urls)),url(r'^$', index),url(r'^about/', about),url(r'^list/([0-9a-zA-Z]+)/$', disp_detail),url(r'^list/$', listing),
]

about.html 比之前多加一个回到首页的链接:

<!-- about.html -->
<!DOCTYPE html>
<html>
<head><meat charset='utf-8'><title>About Myself</title>
</head>
<body>
<h2>Zhe-Rui Chang</h2>
<hr>
<p>
Hi, I am Zhe-Rui Chang.Nice to meet you!
</p>
<hr>
<a href='/'>回首页<a>
</body>
</html>

显示所有手机列表list.html 多加一个对应每个产品的链接

<!-- list.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>手机列表</title>
</head>
<body>
<h2>以下是销售中的手机列表</h2>
<hr>
<table width=400 boder=1 bgcolor='#ccffcc'><tr><td>产品名</td><td>售价</td><td>型号</td></tr>
{% for p in products %}<tr><td><a href='/list/{{p.sku}}/'>{{p.name}}<a></td><td>{{p.price}}</td><td>{{p.size}}</td></tr>
{% endfor %}
</table>
<hr>
<a href='/'>回首页<a>
</body>
</html>

显示单一产品详情的disp.html

<!-- disp.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>{{product.name}}</title>
</head>
<body>
<h2>{{product.name}}</h2>
<hr>
<table width=400 border=1 bgcolor='#ccffcc'>
<tr><td>产品编号</td><td>{{product.sku}}</td></tr>
<tr><td>产品名称</td><td>{{product.name}}</td></tr>
<tr><td>售价</td><td>{{product.price}}</td></tr>
<tr><td>产品型号</td><td>{{product.size}}</td></tr>
</table>
<a href='/list'>返回列表</a>
</body>
</html>

使用了template网页显示的技巧后,view.py中各个函数就变得比较简单了。

#_*_ coding: utf-8 _*_
from django.shortcuts import render
from django.http import HttpResponse,Http404
from myapp.models import Product
from django.template.loader import get_template
import random
# Create your views here.def disp_detail(request, sku):try:p = Product.objects.get(sku=sku)except Product.DoesNotExist:raise Http404('找不到指定的产品编号')template = get_template('disp.html')html = template.render({'product':p})return HttpResponse(html)def listing(request): products = Product.objects.all()template = get_template('list.html')html = template.render({'products':products})return HttpResponse(html)def index(request):template = get_template('index.html')quotes = ['今日事,今日毕','要收获,先付出','知识就是力量','一个人的个性就是他的命运']html = template.render({'quote':random.choice(quotes)})return HttpResponse(html)def about(request):template = get_template('about.html')html = template.render()return HttpResponse(html)

Django学习(三)——MVC架构相关推荐

  1. Django学习(三):中间件

    一,中间件的概念 中间件是一个钩子框架,它们可以介入Django 的请求和响应处理过程. 它是一个轻量级.底层的"插件"系统,用于在全局修改Django 的输入或输出. 每个中间件 ...

  2. django 学习 (三) 模板变量

    将views.py中的变量传递给html模板来显示,变量是以字典的形式传递给html模板文件显示的. 模板文件里以字典的{{健名}}来得到健值. 可传递的变量有以下几种形式 1. 基本变量 retur ...

  3. spring struts2 mybatis框架学习总结(mvc三层架构)

    spring struts2 mybatis框架学习总结(mvc三层架构) ssi的框架主要是由struts2,spring以及ibatis组成,他们负责各层之间的交互与协作,从而实现整个web端的功 ...

  4. Django介绍和虚拟环境(django特点、MVC、MVT、Django学习资料)

    MVT流程: 创建Django项目和应用 django-admin startproject name python manager.py startapp name 视图和ULR 视图的请求和响应 ...

  5. Django学习日志三:模型层

    Django学习日志三:模型层1 日志一我们学习了Django的配置,详见: Django学习日志一Django的配置 日志二我们学习了创建第一个django项目,详见: Django学习日志二--创 ...

  6. MyBatis学习:简单认识一下MVC架构模式和三层架构

    1.本篇博客的背景和目的 目前我本人正在学习MyBatis框架,在原先了解并且懵懵懂懂使用的基础上,开始系统正式的学习.本篇博客阐述一下MVC架构模式和三层架构,以及明晰一下我们通常在Web项目中的编 ...

  7. ExtJS学习:MVC模式案例(三)

    在ExtJS案例系列教程的前两讲,我们了解了该案例的最终实现效果,并且在ExtJS学习:MVC模式案例(二)中我们添加Viewport.js和demoController.js两个文件,实现了对整个网 ...

  8. Java web学习——Spring MVC项目实例,三层架构通过JDBC链接SQLServer2012

    Spring MVC架构原理?原理篇 1.新建项目 File-New-Other,选择Dynamic web project 项目建好后的目录结构如下: 2.导入jar包 导入spring mvc框架 ...

  9. Java学习-MVC架构模式

    目录 1 传统方式处理业务的缺点 2 MVC架构模式理论基础 4 MVC架构模式如何设计 4.1 设计JDBC工具类的封装 4.2 创建封装数据的对象 4.3 设计Dao模式 4.4 业务逻辑编写 4 ...

  10. YXcms(mvc架构php的cms)简单学习与审计

    实践学习php,thinkphp,Redis,vue,uni-app等技术,推荐开源电商系统likeshop,可以借鉴思路,可去版权免费商用,gitee下载地址: https://gitee-gith ...

最新文章

  1. 无线网中的一些技术名词和解释
  2. 【错误归纳】E: Sub-process /usr/bin/dpkg returned an error code (1)子进程 已安装 post-installation 脚本 返回了错误号 1
  3. linux查看文件及文件夹的大小
  4. gdi在固定范围内绘图_寿光计算机绘图CAD学费诚信经营
  5. 2. getline()和get()
  6. 验证日期时间的正则表达式
  7. MoreResult 同事返回多个数据集
  8. springboot 常用插件
  9. 洛谷——P1739 表达式括号匹配
  10. linux 多窗口查看多命令的操作结果
  11. 金蝶K3 WISE 12.3版本系统部署指南
  12. 【学习OpenCV4】聊聊图像格式
  13. Docker架设服务器系列
  14. Exception [WinError 995] 由于线程退出或应用程序请求 的解决办法
  15. 猫哥教你写爬虫 037--爬虫-宝宝要听歌
  16. js实现表单及时验证功能 用户信息立即验证
  17. STM32+ws2812灯条,点灯升级版
  18. Unity 2D精灵分割图片注意事项
  19. Macbook pro 安装Homebrew 软件
  20. Android 环境的安装

热门文章

  1. 出售视频聊天室源码 功能类似 YY 齐秀
  2. 基于蒙特卡洛随机潮流研究(Matlab代码实现)
  3. SpatialHadoop中空间索引系列之(三)格网索引原理
  4. 量子计算: 第四次工业革命的引擎
  5. videojs自动播放
  6. Python 采用Scrapy爬虫框架爬取豆瓣电影top250
  7. gradle的安装配置及使用
  8. BES(恒玄) 提示音解析
  9. 用笔记本通过网线给台式机共享网络
  10. uniapp获取元素距离顶部的距离