MVC框架

MVC简介

MVC最初是由施乐公司旗下的帕罗奥多研究中心中的一位研究人员给 smalltalk语言发明的一中软件设计模式。

  • MVC的产生理念: 分工。让专门的人去做专门的事。
  • MVC的核心思想: 解耦。

MVC的思想被应用在的web开发的方面,产生了web MVC框架。

Web MVC框架模块功能

通过浏览器注册用户信息

M:Model,模型, 和数据库进行交互。
V:View,视图, 产生html页面。
C:Controller,控制器, 接收请求,进行处理,与M和V进行交互,返回应答。

Django

Django是劳伦斯出版集团的开发人员为开发新闻内容网站而设计出来的一个软件,它遵循MVC思想,但是有自己的一个名词,叫做MVT。Django遵循快速开发和DRY原则。

MVT各部分功能


M:Model,模型, 和MVC中M功能相同,和数据库进行交互。
V:View,视图, 和MVC中C功能相同,接收请求,进行处理,与M和T进行交互,返回应答。
T:Template,模板, 和MVC中V功能相同,产生html页面。

虚拟环境


安装python包的命令: sudo pip3 install 包名
包的安装路径:/usr/local/lib/python3.5/dist-packages
在同一个python环境中安装同一个包的不同版本,后安装的包会把原来安装的包覆盖掉。这样,如果同一台机器上两个项目依赖于相同包的不同版本,则会导致一些项目运行失败。
解决的方案就是:虚拟环境
虚拟环境是真实python环境的复制版本。
在虚拟环境中使用的python是复制的python,安装python包也是安装在复制的python中。
/home/.virtualenvs/虚拟环境/lib/python

安装和配置

安装虚拟环境的命令:

sudo pip install virtualenv #安装虚拟环境
sudo pip install virtualenvwrapper #安装虚拟环境扩展包

编辑家目录下面的.bashrc文件,添加下面两行。

export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh

使用source .bashrc使其生效一下。

使用

创建虚拟环境命令:

mkvirtualenv + 虚拟环境名

创建python3虚拟环境:

mkvirtualenv -p python3 + 虚拟环境名

进入虚拟环境工作:

workon + 虚拟环境名

查看机器上有多少个虚拟环境:

workon 空格 + 两个tab键

退出虚拟环境

deactivate

删除虚拟环境:

rmvirtualenv + 虚拟环境名

虚拟环境下安装命令:

pip install 包名
apt-get install 软件名

注意:
不能使用sudo pip install 包名,这个命令会把包安装到真实的主机环境上而不是安装到虚拟环境中。
查看虚拟环境中安装了哪些python包:

pip list
pip freeze

安装django环境:

pip install Django==x.x.x   # x.x.x为指定版本号

创建Django项目

进入虚拟环境后

django-admin startproject + 项目名

项目目录如下:

.
├── dj_test
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

__init__.py: 说明dj_test是一个python包。
settings.py: 项目的配置文件。
urls.py: 进行url路由的配置。
wsgi.py: web服务器和Django交互的入口。
manage.py: 项目的管理文件。

创建Django应用

进入项目目录后创建应用,命令如下:

python manage.py startapp +  应用名

应用目录如下:

.
├── admin.py
├── __init__.py
├── migrations
│   └── __init__.py
├── models.py
├── tests.py
└── views.py

__init__.py: 说明目录是一个Python模块。
models.py: 写和数据库项目的内容, 设计模型类。
views.py: ,接收请求,进行处理,与M和T进行交互,返回应答。
定义处理函数,视图函数。
tests.py: 写测试代码的文件。
admin.py: 网站后台管理相关的文件。

应用注册

建立应用和项目之间的联系,需要对应用进行注册。
修改settings.py中的INSTALLED_APPS配置项。

启动项目

开发服务器
在开发阶段,为了能够快速预览到开发的效果,django提供了一个纯python编写的轻量级web服务器,仅在开发阶段使用。
返回上级项目目录中,运行服务器命令如下:

python manage.py runserver ip:端口

可以不写IP和端口,默认IP是127.0.0.1,默认端口为8000。

模型类

ORM框架
O是object,也就类对象的意思,R是relation,翻译成中文是关系,也就是关系数据库中数据表的意思,M是mapping,是映射的意思。在ORM框架中,它帮我们把类和数据表进行了一个映射,可以让我们通过类和类对象就能操作它所对应的表格中的数据。ORM框架还有一个功能,它可以根据我们设计的类自动帮我们生成数据库中的表格,省去了我们自己建表的过程。
django中内嵌了ORM框架,不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据表的增删改查操作。
使用django进行数据库开发的步骤如下:

  • 在models.py中定义模型类
  • 迁移
  • 通过类和对象完成数据增删改查操作

定义模型类

模型类定义在models.py文件中,必须继承自models.Model类。

不需要定义主键列,在生成时会自动添加,并且值为自动增长。

设计BookInfo类。

# 图书类-一类
class BookInfo(models.Model):"""需要继承models.Model才是模型类"""# 图书名称:CharField()指定为字符串类型,max_length为指定字符串最大长度btitle = models.CharField(max_length=20)# 图书出版日版:DataField()声明是一个日期类型bpub_date = models.DateField()

模型类生成表

定义好的模型类,通过迁移生成相应的表,迁移前目录结构如下:

迁移由两步完成:

  • 生成迁移文件:根据模型类生成创建表的迁移文件。
  • 执行迁移:根据第一步生成的迁移文件在数据库中创建表。

生成迁移文件

python manage.py makemigrations

执行迁移生成表

python manage.py migrate

生成表名的默认格式:应用名_模型类名小写

迁移后,目录文件如下:

Django默认采用sqlite3数据库,上图中的db.sqlite3就是Django框架帮我们自动生成的数据库文件。 sqlite3是一个很小的数据库,通常用在手机中,它跟mysql一样,我们也可以通过sql语句来操作它。
安装sqliteman命令

sudo apt-get install sqliteman

同样的方法设计HeroInfo类。

# 英雄人物类-多类
# 英雄名hname 英雄性别hgender 年龄hage 备注hcomment
# 关系属性:book 建立图书类和英雄类之间的一对多关系
class HeroInfo(models.Model):hname = models.CharField(max_length=20)# 性别:BooleanField说明是bool类型,default默认值,false为男hgender = models.BooleanField(default = False)hcomment = models.CharField(max_length=128)# 即在多类表中创建与一类表关联的外键# 关系属性对应的表的字段名格式为:关系属性名_id 例如:hbook_idhbook = models.ForeignKey("BookInfo")

Models.ForeignKey可以建立两个模型类之间一对多的关系,django在生成表的时候,就会在多端的表中创建一列作为外键,建立两个表之间一对多的关系。

数据操作

完成数据表的迁移之后,下面就可以通过进入项目的shell,进行简单的API操作。如果需要退出项目,可以使用ctrl+d快捷键或输入quit()。

进入项目shell的命令:

python manage.py shell

首先导入模型类:

from booktest.models import BookInfo

查询所有图书信息:

BookInfo.objects.all()

向booktest_bookinfo表中插入一条数据

b = BookInfo() #定义一个BookInfo类的对象
b.btitle ='天龙八部' #定义b对象的属性并赋值
from datetime import date
b.bpub_date = date(1990,10,11)
b.save() #才会将数据保存进数据库

查询出booktest_bookinfo表中id为1的数据。

b = BookInfo.objects.get(id=1)

修改b对应图书的出版日期

b.bpub_date = date(1989,10,21)
b.save() #才会更新表格中的数据

删除图书信息

b.delete()

对象的关联操作

向booktest_heroInfo表中插入一条数据。

from booktest import HeroInfo
h = HeroInfo()
h.hname = '郭靖'
h.hgender = False
h.hcomment = ‘降龙十八掌’
b2 = BookInfo.objects.get(id=2)
h.hbook = b2  #给关系属性赋值,英雄对象所属的图书对象
h.save()

图书与英雄是一对多的关系,django中提供了关联的操作方式。
获得关联集合:返回当前book对象的所有hero。

b.heroinfo_set.all()

后台管理

使用Django的管理模块,需要按照如下步骤操作:

  • 管理界面本地化
  • 创建管理员
  • 注册模型类
  • 自定义管理页面

本地化
语言和时区的本地化。
修改settings.py文件。

LANGUAGE_CODE = 'zh-hans' #使用中国语言
TIME_ZONE = 'Asia/Shanghai' #使用中国上海时间


创建管理员
创建管理员的命令如下,按提示输入用户名、邮箱、密码。

python manage.py createsuperuser


接下来启动服务器。

python manage.py runserver

输入前面创建的用户名、密码完成登录。

登录成功后界面如下,但是并没有图书、英雄的管理入口,接下来进行模型类注册。
登录后台管理后,默认没有我们创建的应用中定义的模型类,需要在自己应用中的admin.py文件中注册,才可以在后台管理中看到,并进行增删改查操作。

重写models中定义模型类的__str__方法可以改变后台管理页面的显示

自定义管理页面
自定义模型管理类。模型管理类就是告诉django在生成的管理页面上显示哪些内容。
打开booktest/admin.py文件,自定义类,继承自admin.ModelAdmin类。
属性list_display表示要显示哪些属性

class BookInfoAdmin(admin.ModelAdmin):list_display = ['id', 'btitle', 'bpub_date']

修改模型类BookInfo的注册代码

admin.site.register(BookInfo, BookInfoAdmin)

视图

在Django中,通过浏览器去请求一个页面时,使用视图函数来处理这个请求的,视图函数处理之后,要给浏览器返回页面内容。
使用视图时需要进行两步操作:

  • 定义视图函数
  • 配置URLconf

定义视图
视图就是一个Python函数,被定义在views.py中。
视图的必须有一个参数,一般叫request,视图必须返回HttpResponse对象,HttpResponse中的参数内容会显示在浏览器的页面上。
打开booktest/views.py文件,定义视图index如下

from django.http import HttpResponse
def index(request):return HttpResponse("index")

配置URLconf
查找视图的过程
请求者在浏览器地址栏中输入url,请求到网站后,获取url信息,然后与编写好的URLconf逐条匹配,如果匹配成功则调用对应的视图函数,如果所有的URLconf都没有匹配成功,则返回404错误。
一条URLconf包括url规则、视图两部分:
url规则使用正则表达式定义。
视图就是在views.py中定义的视图函数。
需要两步完成URLconf配置:

  • 在应用中定义URLconf
  • 包含到项目的URLconf中

在booktest/应用下创建urls.py文件,

包含到项目中:打开test1/urls.py文件,为urlpatterns列表增加项如下:

配置url时,有两种语法格式:

  • url(正则表达式,视图函数名)
  • url(正则表达式,include(应用中的urls文件))

url匹配的过程

请求访问
视图和URLconf都定义好了,运行服务后:

模板

在Django中,将前端的内容定义在模板中,然后再把模板交给视图调用
创建模板
为应用booktest下的视图index创建模板index.html,目录结构如下图:

设置查找模板的路径:打开test1/settings.py文件,设置TEMPLATES的DIRS值

'DIRS': [os.path.join(BASE_DIR, 'templates')]


定义模板
打开templtes/booktest/index.html文件

<html>
<head><title>图书列表</title>
</head>
<body><h1>{{title}}</h1>{%for i in list%}{{i}}<br>{%endfor%}
</body>
</html>

给模板文件传递数据
在模板中输出变量语法如下,变量可能是从视图中传递过来的,也可能是在模板中定义的。

{{变量名}}

在模板中编写代码段语法如下:

{%代码段%}

for循环:

{% for i in list %}list不为空时执行的逻辑
{% empty %}list为空时执行的逻辑
{% endfor %}

视图调用模板
调用模板分为三步骤:

  • 加载模板文件
    去模板目录下面获取html文件的内容,得到一个模板对象。
  • 定义模板上下文
    向模板文件传递数据。
  • 模板渲染
    得到一个标准的html内容。

打开booktst/views.py文件,调用上面定义的模板文件

from django.http import HttpResponse
from django.template import loader,RequestContextdef index(request):# 1.获取模板template=loader.get_template('booktest/index.html')# 2.定义模板上下文context=RequestContext(request,{'title':'图书列表','list':range(10)})# 3.渲染模板res_html = template.render(context)# 4.返回浏览器应答return HttpResponse(res_html)

打开浏览器刷新页面,显示效果如下

视图调用模板简写
视图调用模板都要执行以上三部分,于是Django提供了一个函数render封装了以上代码。 方法render包含3个参数:

  • 第一个参数为request对象
  • 第二个参数为模板文件路径
  • 第三个参数为字典,表示向模板中传递的上下文数据

打开booktst/views.py文件,调用render的代码如下:

from django.shortcuts import renderdef index(request):context={'title':'图书列表','list':range(10)}return render(request,'booktest/index.html',context)

模型

ORM

对象-关系映射(ORM,Object-Relation Mapping),是随着面向对象的软件开发方法发展而产生的。面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射ORM系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。O/R中字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。目前流行的ORM产品如Java的Hibernate,.Net的EntityFormerWork等。
在MVC框架中的Model模块中都包括ORM,对于开发人员主要带来了如下好处:

  • 实现了数据模型与数据库的解耦,通过简单的配置就可以轻松更换数据库,而不需要修改代码。
  • 只需要面向对象编程,不需要面向数据库编写代码。
  • 在MVC中Model中定义的类,通过ORM与关系型数据库中的表对应,对象的属性体现对象间的关系,这种关系也被映射到数据表中。

O(objects):类和对象。
R(Relation):关系,关系数据库中的表格。
M(Mapping):映射。
Django ORM框架的功能:

  • 建立模型类和表之间的对应关系,允许我们通过面向对象的方式来操作数据库。
  • 根据设计的模型类生成数据库中的表格。
  • 通过方便的配置就可以进行数据库的切换。

Django ORM示意图

Django数据库配置

mysql部分命令
登录mysql数据库:

mysql –uroot –p

查看有哪些数据库:

show databases

创建数据库:

create database test2 charset=utf8; #切记:指定编码

使用数据库:

use test2;

查看数据库中的表:

show tables;

Django配置使用mysql数据库

创建新的Django项目test2

django-admin startproject test2

打开test2/settings.py文件,找到DATABASES项,默认使用SQLite3数据库

修改settings.py中的DATABASES。

DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'test2', #数据库名字,'USER': 'root', #数据库登录用户名'PASSWORD': 'mysql', #数据库登录密码'HOST': 'localhost', #数据库所在主机'PORT': '3306', #数据库端口}
}

注意:django框架不会自动帮我们生成mysql数据库,所以我们需要自己去创建。

进入test2目录,创建应用booktest

python manage.py stratapp booktest

将应用booktest注册到项目中:打开test2/settings.py文件,找到INSTALLED_APPS项,注册booktest

打开booktest/models.py文件,定义模型类如下

from django.db import models#定义图书模型类BookInfo
class BookInfo(models.Model):btitle = models.CharField(max_length=20)#图书名称bpub_date = models.DateField()#发布日期bread = models.IntegerField(default=0)#阅读量bcomment = models.IntegerField(default=0)#评论量isDelete = models.BooleanField(default=False)#逻辑删除#定义英雄模型类HeroInfo
class HeroInfo(models.Model):hname = models.CharField(max_length=20)#英雄姓名hgender = models.BooleanField(default=True)#英雄性别isDelete = models.BooleanField(default=False)#逻辑删除hcomment = models.CharField(max_length=200)#英雄描述信息hbook = models.ForeignKey('BookInfo')#英雄与图书表的关系为一对多,所以属性定义在英雄模型类中

生成迁移文件

python manage.py makemigrations

生成迁移文件的时候出现错误,原因是把数据库切换成了mysql,需要安装pymysql模块之后,Django框架才可以操作mysql数据库。安装命令如下:
python2需要安装mysql-python

pip install mysql-python

python3需要安装pymysql:

pip install pymysql

安装成功之后,在test2/_init_.py文件中加上如下代码:

import pymysql
pymysql.install_as_MySQLdb()


设计BookInfo,增加属性bread和bcomment,另外设置软删除标记属性isDelete。
设计HeroInfo类,增加软删除标记属性isDelete。
软删除标记:删除数据时不做真正的删除,而是把标记数据设置为1表示删除,目的是防止重要的数据丢失

执行迁移

python manage.py makemigrations
python manage.py migrate


在终端的mysql中查看两表结构为

插入数据

insert into booktest_bookinfo(btitle,bpub_date,bread,bcomment,isDelete) values
('射雕英雄传','1980-5-1',12,34,0),
('天龙八部','1986-7-24',36,40,0),
('笑傲江湖','1995-12-24',20,80,0),
('雪山飞狐','1987-11-11',58,24,0);insert into booktest_heroinfo(hname,hgender,hbook_id,hcomment,isDelete) values
('郭靖',1,1,'降龙十八掌',0),
('黄蓉',0,1,'打狗棍法',0),
('黄药师',1,1,'弹指神通',0),
('欧阳锋',1,1,'蛤蟆功',0),
('梅超风',0,1,'九阴白骨爪',0),
('乔峰',1,2,'降龙十八掌',0),
('段誉',1,2,'六脉神剑',0),
('虚竹',1,2,'天山六阳掌',0),
('王语嫣',0,2,'神仙姐姐',0),
('令狐冲',1,3,'独孤九剑',0),
('任盈盈',0,3,'弹琴',0),
('岳不群',1,3,'华山剑法',0),
('东方不败',0,3,'葵花宝典',0),
('胡斐',1,4,'胡家刀法',0),
('苗若兰',0,4,'黄衣',0),
('程灵素',0,4,'医术',0),
('袁紫衣',0,4,'六合拳',0);


定义视图
打开booktest/views.py文件,定义视图代码如下:

from django.shortcuts import render,redirect
from booktest.models import BookInfo,HeroInfo
from datetime import date#查询所有图书并显示
def index(request):books=BookInfo.objects.all()return render(request,'booktest/index.html',{'books':books})#创建新图书
def create(request):book=BookInfo()book.btitle = '流星蝴蝶剑'book.bpub_date = date(1995,12,30)book.save()#转向到首页return redirect('/index')#逻辑删除指定编号的图书
def delete(request,id):book=BookInfo.objects.get(id=int(id))book.delete()#转向到首页return redirect('/index')

配置url
打开test2/urls.py文件,配置url如下:

from django.conf.urls import include, url
from django.contrib import adminurlpatterns = [url(r'^admin/', include(admin.site.urls)),#引入booktest的url配置url(r'^',include('booktest.urls')),
]

在booktest应用下创建urls.py文件,代码如下:

from django.conf.urls import url
from booktest import viewsurlpatterns=[url(r'^index$',views.index),url(r'^delete(\d+)/$',views.delete),url(r'^create/$',views.create),
]

创建模板
打开test2/settings.py文件,配置模板查找目录TEMPLATES的DIRS。

'DIRS': [os.path.join(BASE_DIR,'templates')],


创建templates/booktest/index.html文件。

模板代码如下:

<html>
<head><title>复习案例</title>
</head>
<body>
<a href="/create/">创建</a>
<ul>
{%for book in books%}<li>{{book.btitle}}--<a href="/delete{{book.id}}/">删除</a></li>
{%endfor%}
</ul>
</body>
</html>

运行
运行服务器。

python manage.py runserver

在浏览器中查看。

模型类

Django根据属性的类型确定以下信息:

  • 当前选择的数据库支持字段的类型
  • 渲染管理表单时使用的默认html控件
  • 在管理站点最低限度的验证

django会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。
默认创建的主键列属性为id,可以使用pk代替,pk全拼为primary key。
**注意:**pk是主键的别名,若主键名为id2,那么pk是id2的别名。
属性命名限制:

  • 不能是python的保留关键字。
  • 不允许使用连续的下划线,这是由django的查询方式决定的,在第4节会详细讲解查询。
  • 定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下:
属性=models.字段类型(选项)

字段类型
使用时需要引入django.db.models包,字段类型如下:

  • AutoField:自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性。
  • BooleanField:布尔字段,值为True或False。
  • NullBooleanField:支持Null、True、False三种值。
  • CharField(max_length=字符长度):字符串。参数max_length表示最大字符个数。
  • TextField:大文本字段,一般超过4000个字符时使用。
  • IntegerField:整数。
  • DecimalField(max_digits=None, decimal_places=None):十进制浮点数。参数max_digits表示总位数。参数decimal_places表示小数位数。
  • FloatField:浮点数。
  • DateField[auto_now=False, auto_now_add=False]):日期。
    参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false。
    参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false。
    参数auto_now_add和auto_now是相互排斥的,组合将会发生错误。
  • TimeField:时间,参数同DateField。
  • DateTimeField:日期时间,参数同DateField。
  • FileField:上传文件字段。
  • ImageField:继承于FileField,对上传的内容进行校验,确保是有效的图片。

选项
通过选项实现对字段的约束,选项如下:

  • null:如果为True,表示允许为空,默认值是False。
  • blank:如果为True,则该字段允许为空白,默认值是False。
  • 对比:null是数据库范畴的概念,blank是表单验证范畴的。
  • db_column:字段的名称,如果未指定,则使用属性的名称。
  • db_index:若值为True, 则在表中会为此字段创建索引,默认值是False。
  • default:默认值。
  • primary_key:若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用。
  • unique:如果为True, 这个字段在表中必须有唯一值,默认值是False。
    null是数据库范畴的概念,blank是后台管理页面表单验证范畴的。
    当修改模型类之后,如果添加的选项不影响表的结构,则不需要重新做迁移,商品的选项中default和blank不影响表结构。

查询

mysql的日志文件

mysql.log是mysql的日志文件,里面记录的对MySQL数据库的操作记录。默认情况下mysql的日志文件没有产生,需要修改mysql的配置文件,步骤如下:
使用下面的命令打开mysql的配置文件,去除68,69行的注释,然后保存。

sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf


重启mysql服务,就会产生mysql日志文件。

sudo service mysql restart

使用如下命令打开mysql日志文件。

sudo tail -f /var/log/mysql/mysql.log #可以实时查看数据库的日志内容

查询函数

通过模型类.objects属性可以调用如下函数,实现对模型类对应的数据表的查询。

  • get
    返回表中满足条件的一条且只能有一条数据。
    返回值是一个模型类对象。 参数中写查询条件。

    • 如果查到多条数据,则抛异常MultipleObjectsReturned。
    • 查询不到数据,则抛异常:DoesNotExist。
  • all
    返回模型类对应表格中的所有数据。
    返回值是QuerySet类型 查询集

  • filter
    返回满足条件的数据。
    返回值是QuerySet类型 参数写查询条件。

  • exclude
    返回不满足条件的数据。
    返回值是QuerySet类型 参数写查询条件。

  • order_by
    对查询结果进行排序。
    返回值是QuerySet类型 参数中写根据哪些字段进行排序。

条件格式:
模型类属性名__条件名=值 (双下划线)

  • 判等 条件名:exact
    查询编号为1的图书。

    BookInfo.objects.get(id=1);
    BookInfo.objects.get(id__exact=1);
    
  • 模糊查询
    查询书名包含’传’的图书。contains

    BookInfo.objects.filter(btitle__contains = '传');
    

    查询书名以’部’结尾的图书 endswith 开头:startswith

    BookInfo.objects.filter(btitle__endwith='传');
    
  • 空查询 isnull
    查询书名不为空的图书。isnull

    BookInfo.objects.filter(btitle__isnull==False);
    
  • 范围查询 in
    查询id为1或3或5的图书。

    BookInfo.objects.fiter(id__in=[1,3,5]);
    
  • 比较查询 gt(greate than) lt(less than) gte(equal) 大于等于
    lte 小于等于
    查询id大于3的图书

    BookInfo.objects.filter(id__gt=3);
    
  • 日期查询
    查询1980年1月1日后发表的图书

    from datetime import date
    BookInfo.objects.filter(bpub_date__gt=(1980,1,1));
    
  • exclude方法
    查询id不为3的图书信息。

    BookInfo.objects.filter(id__exclude=3);
    
  • order_by方法
    查询所有图书的信息,按照id从小到大进行排序

    BookInfo.objects.all().order_by('id');
    

    查询所有图书的信息,按照id从大到小进行排序

    BookInfo.objects.all().order_by('-id');
    

    把id大于3的图书信息按阅读量从大到小排序显示

    BookInfo.objects.filter(id__gt=3).order_by('-bread');
    

F对象

F对象用于类属性之间的比较
使用之前需要先导入

from django.db.models import F

查询图书阅读量大于评论量图书信息

BookInfo.objects.filter(bread__gt=F('bcomment'));

查询图书阅读量大于2倍评论量图书信息

BookInfo.objects.filter(bread__gt=F('bcomment')*2);

Q对象

多个过滤器逐个调用表示逻辑与关系,同sql语句中where部分的and关键字
使用之前需要先导入:

from django.db.models import Q

查询id大于3且阅读量大于30的图书的信息

BookInfo.objects.filter(id__gt=3,bread__gt=30);
BookInfo.objects.filter(Q(id__gt=3)&Q(bread__gt=30));

Q对象可以使用&、|连接,&表示逻辑与,|表示逻辑或
查询id大于3或者阅读量大于30的图书的信息

BookInfo.objects.filter(Q(id__gt=3)|Q(bread__gt=30));

Q对象前可以使用~操作符,表示非not
查询id不等于3图书的信息

BookInfo.objects.filter(~Q(id=3));

聚合函数

对查询结果进行聚合操作:sum count avg max min
aggregate:调用这个函数来使用聚合。 返回值是一个字典
使用前需先导入聚合类:

from django.db.models import Sum,Count,Max,Min,Avg

查询所有图书阅读量的总和

BookInfo.objects.aggregate(Sum('bread'));

查询所有图书的数目

BookInfo.objects.all().aggregate(Count('id'));

count函数 返回值是一个数字
作用:统计满足条件数据的数目
统计所有图书的数目

BookInfo.objects.all().count();
BookInfo.objects.count();

统计id大于3的所有图书的数目

BookInfo.objects.filter(id__gt=3).count();

查询集

查询集表示从数据库中获取的对象集合,在管理器上调用某些过滤器方法会返回查询集,查询集可以含有零个、一个或多个过滤器。过滤器基于所给的参数限制查询的结果,从Sql的角度,查询集和select语句等价,过滤器像where和limit子句。

返回查询集的过滤器如下:

  • all():返回所有数据。
  • filter():返回满足条件的数据。
  • exclude():返回满足条件之外的数据,相当于sql语句中where部分的not关键字。
  • order_by():对结果进行排序。

返回单个值的过滤器如下:

  • get():返回单个满足条件的对象
    如果未找到会引发"模型类.DoesNotExist"异常。
    如果多条被返回,会引发"模型类.MultipleObjectsReturned"异常。
  • count():返回当前查询结果的总条数。
  • aggregate():聚合,返回一个字典。

判断某一个查询集中是否有数据:

  • exists():判断查询集中是否有数据,如果有则返回True,没有则返回False。

两大特性
惰性执行:创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用。
缓存:使用同一个查询集,第一次使用时会发生数据库的查询,然后把结果缓存下来,再次使用这个查询集时会使用缓存的数据。
限制查询集
可以对查询集进行取下标或切片操作,等同于sql中的limit和offset子句。
注意:不支持负数索引。
对查询集进行切片后返回一个新的查询集,不会立即执行查询。
如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,[0:1].get()如果没有数据引发DoesNotExist异常。

模型类关系

关系字段类型
关系型数据库的关系包括三种类型:

  • ForeignKey:一对多,将字段定义在多的一端中。
  • ManyToManyField:多对多,将字段定义在任意一端中。
  • OneToOneField:一对一,将字段定义在任意一端中。

一对多关系

#定义图书模型类BookInfo
class BookInfo(models.Model):btitle = models.CharField(max_length=20)#图书名称bpub_date = models.DateField()#发布日期bread = models.IntegerField(default=0)#阅读量bcomment = models.IntegerField(default=0)#评论量isDelete = models.BooleanField(default=False)#逻辑删除#定义英雄模型类HeroInfo
class HeroInfo(models.Model):hname = models.CharField(max_length=20)#英雄姓名hgender = models.BooleanField(default=True)#英雄性别isDelete = models.BooleanField(default=False)#逻辑删除hcomment = models.CharField(max_length=200)#英雄描述信息hbook = models.ForeignKey('BookInfo')#英雄与图书表的关系为一对多,所以属性定义在英雄模型类中

多对多关系

class TypeInfo(models.Model):tname = models.CharField(max_length=20) #新闻类别class NewsInfo(models.Model):ntitle = models.CharField(max_length=60) #新闻标题ncontent = models.TextField() #新闻内容npub_date = models.DateTimeField(auto_now_add=True) #新闻发布时间ntype = models.ManyToManyField('TypeInfo') #通过ManyToManyField建立TypeInfo类和NewsInfo类之间多对多的关系

关联查询

Django中也能实现类似于join查询。
通过对象执行关联查询
在定义模型类时,可以指定三种关联关系,最常用的是一对多关系,在一对多关系中,一对应的类叫做一类,多对应的那个类叫做多类,多类中定义的建立关联的类属性叫做关联属性

查询id为1的图书关联的英雄的信息

b = BookInfo.objects.get(id__exact = 1);
b.heroinfo_set.all();

通过模型类查询

HeroInfo.objects.filter(hbook__id=1);

查询id为1的英雄关联的图书信息

h = HeroInfo.objects.filter(id__exact=1);
h.hbook;

通过模型类查询

BookInfo.objects.fliter(heroinfo__id=1);

通过对象执行关联查询
由一到多的访问语法:
一对应的模型类对象.多对应的模型类名小写_set
由多到一的访问语法:
多对应的模型类对象.多对应的模型类中的关系类属性名
访问一对应的模型类关联对象的id语法
多对应的模型类对象.关联类属性_id

通过模型类执行关联查询
由多模型类条件查询一模型类数据:
关联模型类名小写__属性名__条件运算符=值
如果没有"__运算符"部分,表示等于,结果和sql中的inner join相同。
由一模型类条件查询多模型类数据: 语法如下:
一模型类关联属性名__一模型类属性名__条件运算符=值

插入、更新和删除

调用一个模型类对象的save方法的时候就可以实现对模型类对应数据表的插入和更新。
调用一个模型类对象的delete方法的时候就可以实现对模型类对应数据表数据的删除。

自关联

对于地区信息、分类信息等数据,表结构非常类似,每个表的数据量十分有限,为了充分利用数据表的大量数据存储功能,可以设计成一张表,内部的关系字段指向本表的主键,这就是自关联的表结构。
自关联是一种特殊的一对多的关系。
案例:显示广州市的上级地区和下级地区。

模型类:

#定义地区模型类,存储省、市、区县信息
class AreaInfo(models.Model):atitle=models.CharField(max_length=30) # 名称aParent=models.ForeignKey('self',null=True,blank=True) # 关系

由一类的对象查询多类的时候:
一类的对象.多类名小写_set.all() #查询所用数据
由多类的对象查询一类的时候:
多类的对象.关联属性 #查询多类的对象对应的一类的对象
由多类的对象查询一类对象的id时候:
多类的对象. 关联属性_id
定义视图

定义模板html

<html>
<head><title>地区</title>
</head>
<body>
当前地区:{{area.atitle}}
<hr/>
上级地区:{{parent.atitle}}
<hr/>
下级地区:
<ul>{%for child in children%}<li>{{child.atitle}}</li>{%endfor%}
</ul>
</body>
</html>

配置urls.py

运行服务 python manage.py runserver

模型实例方法

  • str():在将对象转换成字符串时会被调用。
  • save():将模型对象保存到数据表中,ORM框架会转换成对应的insert或update语句。
  • delete():将模型对象从数据表中删除,ORM框架会转换成对应的delete语句。

模型类的属性

属性objects:管理器,是models.Manager类型的对象,用于与数据库进行交互。
当没有为模型类定义管理器时,Django会为每一个模型类生成一个名为objects的管理器,自定义管理器后,Django不再生成默认管理器objects。
为模型类BookInfo定义管理器books语法如下:

class BookInfo(models.Model):...books = models.Manager()

管理器Manager

管理器是Django的模型进行数据库操作的接口,Django应用的每个模型类都拥有至少一个管理器。Django支持自定义管理器类,继承自models.Manager。

自定义管理器类主要用于两种情况:

  • 修改原始查询集,重写all()方法
  • 向管理器类中添加额外的方法,如向数据库中插入数据。

1) 修改原始查询集,重写all()方法。
打开booktest/models.py文件,定义类BookInfoManager

#图书管理器
class BookInfoManager(models.Manager):def all(self):#默认查询未删除的图书信息#调用父类的成员语法为:super().方法名return super().all().filter(isDelete=False)

在模型类BookInfo中定义管理器

class BookInfo(models.Model):...books = BookInfoManager()

2) 在管理器类中定义创建对象的方法
对模型类对应的数据表进行操作时,推荐将这些操作数据表的方法封装起来,放到模型管理器类中。
打开booktest/models.py文件,定义方法create。

class BookInfoManager(models.Manager):...#创建模型类,接收参数为属性赋值def create_book(self, title, pub_date):#创建模型类对象self.model可以获得模型类book = self.model()book.btitle = titlebook.bpub_date = pub_datebook.bread=0book.bcommet=0book.isDelete = False# 将数据插入进数据表book.save()return book

为模型类BookInfo定义管理器books语法如下

class BookInfo(models.Model):...books = BookInfoManager()

调用语法如下:

调用:book=BookInfo.books.create_book("abc",date(1980,1,1))

元选项

在模型类中定义类Meta,用于设置元信息,如使用db_table自定义表的名字。

视图

视图负责接收请求,进行处理,与M和T进行交互,返回应答。
返回html内容 HttpResponse,也可能重定向 redirect,还可以返回json数据。

视图函数使用

定义视图函数
request参数必须有。是一个HttpRequest类型的对象。参数名可以变化,但不要更改。
配置url
建立url和视图函数之间的对应关系。

url配置的过程

  • 在项目的urls文件中包含具体应用的urls文件,在具体应用的urls文件中包含具体url和视图的对应关系。
  • url配置项是定义在一个名叫urlpatterns的列表中,其中的每一个元素就是一个配置项,每一个配置项都调用url函数。

语法一

url(正则,include('应用.urls'))

例如:

url(r'^',include('booktest.urls')),


这种语法用于项目目录下的urls.py中,目的是将应用的urls配置到应用内部,数据更清晰并且易于维护。
语法二:定义,指定URL和视图函数的对应关系。

应用内部创建的urls.py文件,指定请求地址与视图的对应关系。

url(正则,'视图函数名称')

例如

from django.conf.urls import url
from booktest import views
urlpatterns=[url(r'^$',views.index),
]

错误视图

404:找不到页面,关闭调试模式之后,默认会显示一个标准的错误页面,如果要显示自定义的页面,则需要的templates目录下面自定义一个404.html文件。

  • url没有配置
  • url配置错误

500: 服务器端的错误。如果要显示自定义的页面,则需要的templates目录下面自定义一个500.html文件

  • 视图出错

网站开发完成需要关闭调试模式,在settings.py文件中:
DEBUG=False
ALLOWED_HOST=[ ‘*’]

捕获url参数

进行url匹配时,把所需要的捕获的部分设置成一个正则表达式组,这样django框架就会自动把匹配成功后相应组的内容作为参数传递给视图函数。
在匹配过程中从url中捕获参数,每个捕获的参数都作为一个普通的python字符串传递给视图。

获取值需要在正则表达式中使用小括号,分为两种方式:
位置参数
关键字参数
注意:两种参数的方式不要混合使用,在一个正则表达式中只能使用一种参数方式。

位置参数
直接使用小括号,通过位置参数传递给视图。


关键字参数
在正则表达式部分为组命名。

其中?P部分表示为这个参数定义的名称为num

HttpReqeust对象

服务器接收到http协议的请求后,会根据报文创建HttpRequest对象,这个对象不需要我们创建,直接使用服务器构造好的对象就可以。视图的第一个参数必须是HttpRequest对象,在django.http模块中定义了HttpRequest对象的API。
属性
下面除非特别说明,属性都是只读的。
path:一个字符串,表示请求的页面的完整路径,不包含域名和参数部分。
method:一个字符串,表示请求使用的HTTP方法,常用值包括:‘GET’、‘POST’。
在浏览器中给出地址发出请求采用get方式,如超链接。
在浏览器中点击表单的提交按钮发起请求,如果表单的method设置为post则为post请求。
encoding:一个字符串,表示提交的数据的编码方式。
如果为None则表示使用浏览器的默认设置,一般为utf-8。
这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值。
GET:QueryDict类型对象,类似于字典,包含get请求方式的所有参数。
POST:QueryDict类型对象,类似于字典,包含post请求方式的所有参数。
FILES:一个类似于字典的对象,包含所有的上传文件。
COOKIES:一个标准的Python字典,包含所有的cookie,键和值都为字符串。
session:一个既可读又可写的类似于字典的对象,表示当前的会话,只有当Django 启用会话的支持时才可用。
运行服务器,在浏览器中浏览首页,可以在浏览器“开发者工具”中看到请求信息如下图:

QueryDict对象

  • 定义在django.http.QueryDict
  • HttpRequest对象的属性GET、POST都是QueryDict类型的对象
  • 与python字典不同,QueryDict类型的对象用来处理同一个键带有多个值的情况
  • 方法get():根据键获取值
  • 如果一个键同时拥有多个值将获取最后一个值
  • 如果键不存在则返回None值,可以设置默认值进行后续处理
    dict.get('键',默认值)
    可简写为
    dict['键']
    
  • 方法getlist():根据键获取值,值以列表返回,可以获取指定键的所有值
  • 如果键不存在则返回空列表[],可以设置默认值进行后续处理
    dict.getlist('键',默认值)
    

GET属性

请求格式:在请求地址结尾使用?,之后以"键=值"的格式拼接,多个键值对之间以&连接。

POST属性

使用form表单请求时,method方式为post则会发起post方式的请求,需要使用HttpRequest对象的POST属性接收参数,POST属性是一个QueryDict类型的对象。
表单控件name属性的值作为键value属性的值为值,构成键值对提交。

  • 如果表单控件没有name属性则不提交。
  • 对于checkbox控件,name属性的值相同为一组,被选中的项会被提交,出现一键多值的情况。
  • 键是表单控件name属性的值,是由开发人员编写的。
  • 值是用户填写或选择的。
#接收请求参数
def show_reqarg(request):if request.method == 'GET':a = request.GET.get('a') #获取请求参数ab = request.GET.get('b') #获取请求参数bc = request.GET.get('c') #获取请求参数creturn render(request, 'booktest/show_getarg.html', {'a':a, 'b':b, 'c':c})else:name = request.POST.get('uname') #获取namegender = request.POST.get('gender') #获取genderhobbys = request.POST.getlist('hobby') #获取hobbyreturn render(request, 'booktest/show_postarg.html', {'name':name, 'gender':gender, 'hobbys':hobbys})

HttpResponse对象

视图在接收请求并处理后,必须返回HttpResponse对象或子对象。在django.http模块中定义了HttpResponse对象的API。HttpRequest对象由Django创建,HttpResponse对象由开发人员创建。
运行服务器,在浏览器中浏览首页,可以在浏览器“开发者工具”中看到响应信息如下图:
标号3为响应头信息,点击标号4处可以查看响应体信息。

属性

  • content:表示返回的内容。
  • charset:表示response采用的编码字符集,默认为utf-8。
  • status_code:返回的HTTP响应状态码。
  • content-type:指定返回数据的的MIME类型,默认为’text/html’。
    方法
  • _init_:创建HttpResponse对象后完成返回内容的初始化。
  • set_cookie:设置Cookie信息。
    set_cookie(key, value='', max_age=None, expires=None)
    
  • cookie是网站以键值对格式存储在浏览器中的一段纯文本信息,用于实现用户跟踪。
    • max_age是一个整数,表示在指定秒数后过期。
    • expires是一个datetime或timedelta对象,会话将在这个指定的日期/时间过期。
    • max_age与expires二选一。
    • 如果不指定过期时间,在关闭浏览器时cookie会过期。
  • delete_cookie(key):删除指定的key的Cookie,如果key不存在则什么也不发生。
  • write:向响应体中写数据。

子类JsonResponse

在浏览器中使用javascript发起ajax请求时,返回json格式的数据,此处以jquery的get()方法为例。类JsonResponse继承自HttpResponse对象,被定义在django.http模块中,创建对象时接收字典作为参数。
JsonResponse对象的content-type为’application/json’。

Ajax

异步的javascript。在不全部加载某一个页面部的情况下,对页面进行局的刷新,ajax请求都在后台。
ajax代码执行过程如下:

  • 发起请求。
  • 服务器端视图函数执行。
  • 执行回调函数。

案例:模拟登陆
将图片,css文件,js文件等静态文件,放入static目录下,并配置settings.py。


设计url对应的视图函数login_ajax和负责ajax校验的函数login_ajax_check


编写模板文件login_ajax.html


配置url

子类HttpResponseRedirect

当一个逻辑处理完成后,不需要向客户端呈现数据,而是转回到其它页面,如添加成功、修改成功、删除成功后显示数据列表,而数据的列表视图已经开发完成,此时不需要重新编写列表的代码,而是转到这个视图就可以,此时就需要模拟一个用户请求的效果,从一个视图转到另外一个视图,就称为重定向
Django中提供了HttpResponseRedirect对象实现重定向功能,这个类继承自HttpResponse,被定义在django.http模块中,返回的状态码为302
views.py文件中定义视图

from django.http import HttpResponseRedirect
...
# 定义重定义向视图,转向首页
def red1(request):return HttpResponseRedirect('/')

重定向简写函数redirect
在django.shortcuts模块中为重定向类提供了简写函数redirect。
修改views.py文件中视图:

from django.shortcuts import redirect
...
def red1(request):return redirect('/')

状态保持

浏览器请求服务器是无状态的。无状态指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。无状态的应用层面的原因是:浏览器和服务器之间的通信都遵守HTTP协议。根本原因是:浏览器与服务器是使用Socket套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的Socket连接,而且服务器也会在处理页面完毕之后销毁页面对象。

有时需要保存下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等。 实现状态保持主要有两种方式:

  • 在客户端存储信息使用Cookie。
  • 在服务器端存储信息使用Session。

Cookie
cookie是由服务器生成,存储在浏览器端的一小段文本信息。有时也用其复数形式Cookies,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。

Cookie的特点

  • Cookie以键值对的格式进行信息的存储。
  • Cookie基于域名安全,不同域名的Cookie是不能互相访问的,如访问itcast.cn时向浏览器中写了Cookie信息,使用同一浏览器访问baidu.com时,无法访问到itcast.cn写的Cookie信息。
  • 当浏览器请求某网站时,会将浏览器存储的跟网站相关的所有Cookie信息提交给网站服务器。
  • Cookie是有过期时间的,如果不指定,默认关闭浏览器之后cookie就会过期。

设置cookie和获取cookie




案例:记住用户名
view.py下定义登陆login视图函数和登陆检验函数login_check


编写模板文件

配置urls.py

Session

对于敏感、重要的信息,建议要储在服务器端,不能存储在浏览器中,如用户名、余额、等级、验证码等信息。
在服务器端进行状态保持的方案就是Session。
启用Session
Django项目默认启用Session。
打开settings.py文件,在项MIDDLEWARE_CLASSES中启用Session中间件。禁用Session:将Session中间件删除。

存储方式
打开settings.py文件,设置SESSION_ENGINE项指定Session数据存储的方式,可以存储在数据库、缓存、Redis等。
存储在数据库中,如下设置可以写,也可以不写,这是默认存储方式。

SESSION_ENGINE='django.contrib.sessions.backends.db'

存储在缓存中:存储在本机内存中,如果丢失则不能找回,比数据库的方式读写更快。

SESSION_ENGINE='django.contrib.sessions.backends.cache'

混合存储:优先从本机内存中存取,如果没有则从数据库中存取。

SESSION_ENGINE='django.contrib.sessions.backends.cached_db'

如果存储在数据库中,需要在项INSTALLED_APPS中安装Session应用。

迁移后会在数据库中创建出存储Session的表。

表结构如下图。

由表结构可知,操作Session包括三个数据:键,值,过期时间。

session的特点:

  • session是以键值对进行存储的。
  • session依赖于cookie。唯一的标识码保存在sessionid cookie中。
  • session也是有过期时间,如果不指定,默认两周就会过期。

对象及方法
以键值对的格式写session。

request.session['键']=值

根据键读取值。

request.session.get('键',默认值)

清除所有session,在存储中删除值部分。

request.session.clear()

清除session数据,在存储中删除session的整条数据。

request.session.flush()

删除session中的指定键及值,在存储中只删除某个键及对应的值。

del request.session['键']

设置会话的超时时间,如果没有指定过期时间则两个星期后过期。

request.session.set_expiry(value)

如果value是一个整数,会话将在value秒没有活动后过期。
如果value为0,那么用户会话的Cookie将在用户的浏览器关闭时过期。
如果value为None,那么会话永不过期。

使用Redis存储Session
安装包

pip install django-redis-sessions==0.5.6

修改settings文件,增加如下项:

SESSION_ENGINE = 'redis_sessions.session'
SESSION_REDIS_HOST = 'localhost'
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 2
SESSION_REDIS_PASSWORD = ''
SESSION_REDIS_PREFIX = 'session'

views.py文件,修改session_test视图

def session_test(request):request.session['h1']='hello'return HttpResponse('ok')

管理redis的命令,需要保证redis服务被开启。

查看:ps ajx|grep redis
启动:sudo service redis start
停止:sudo service redis stop
使用客户端连接服务器:redis-cli
切换数据库:select 2
查看所有的键:keys *
获取指定键的值:get name

cookie和session的应用场景

cookie:记住用户名。安全性要求不高。
session:涉及到安全性要求比较高的数据。银行卡账户,密码

模板

作为Web框架,Django提供了模板,用于编写html代码,还可以嵌入模板代码更快更方便的完成页面开发,再通过在视图中渲染模板,将生成最终的html字符串返回给客户端浏览器。模版致力于表达外观,而不是程序逻辑。模板的设计实现了业务逻辑view与显示内容template的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用。

模板包含两部分:

  • 静态部分,包含html、css、js。
  • 动态部分,用于动态去产生一些网页内容。通过模板语言来产生。

Django模板语言,简写DTL,定义在django.template包中。 创建项目后,在"项目名称/settings.py"文件中定义了关于模板的配置。

模板文件的使用

通常是在视图函数中使用模板产生html内容返回给客户端。

  • 加载模板文件 loader.get_template
    获取模板文件的内容,产生一个模板对象。
  • 定义模板上下文 RequeseContext
    给模板文件传递数据。
  • 模板渲染产生html页面内容 render
    用传递的数据替换相应的变量,产生一个替换后的标准的html内容。


模板文件加载顺序

  • 首先去配置的模板目录下面去找模板文件。
  • 去INSTALLED_APPS下面的每个应用的templates去找模板文件,前提是应用中必须有templates文件夹。

模板语言

模板语言简称为DTL。(Django Template Language),模板语言包括4种类型,分别是:变量
标签 过滤器 注释

模板变量

模板变量的作用是计算并输出,变量名必须由字母、数字、下划线(不能以下划线开头)和点组成。
语法如下:

{{模板变量名}}

例如:{{ book.btitle }}

  • 首先把book当成一个字典,把btitle当成键名,进行取值book[‘btitle’]
  • 把book当成一个对象,把btitle当成属性,进行取值book.btitle
  • 把book当成一个对象,把btitle当成对象的方法,进行取值book.btitle

例如:{{book.0}}

  • 首先把book当成一个字典,把0当成键名,进行取值book[0]
  • 把book当成一个列表,把0当成下标,进行取值book[0]

如果解析失败,则产生内容时用空字符串填充模板变量。
使用模板变量时,.前面的可能是一个字典,可能是一个对象,还可能是一个列表。


模板标签

语法如下:

{%代码段%}

for标签语法如下:

{%for item in 列表%}
循环逻辑
{{forloop.counter}}表示当前是第几次循环,从1开始
{%empty%}
列表为空或不存在时执行此逻辑
{%endfor%}



if标签语法如下:

{%if ...%}
逻辑1
{%elif ...%}
逻辑2
{%else%}
逻辑3
{%endif%}

比较运算符如下:
注意:运算符左右两侧不能紧挨变量或常量,必须有空格。

==
!=
<
>
<=
>=

逻辑运算:

and
or
not

过滤器

过滤器用于对模板变量进行操作。
date:改变日期的显示格式。
length:求长度。字符串,列表.
default:设置模板变量的默认值。

  • 使用管道符号|来应用过滤器,用于进行计算、转换操作,可以使用在变量、标签中。
  • 如果过滤器需要参数,则使用冒号:传递参数。

语法如下:

变量|过滤器:参数

长度length,返回字符串包含字符的个数,或列表、元组、字典的元素个数。
默认值default,如果变量不存在时则返回默认值。

data|default:'默认值'

日期date,用于对日期类型的值进行字符串格式化,常用的格式化字符如下:

Y表示年,格式为4位,y表示两位的年。
m表示月,格式为01,02,12等。
d表示日, 格式为01,02等。
j表示日,格式为1,2等。
H表示时,24进制,h表示12进制的时。
i表示分,为0-59。
s表示秒,为0-59。
value|date:"Y年m月j日  H时i分s秒"


自定义过滤器

过滤器就是python中的函数,注册后就可以在模板中当作过滤器使用,自定义过滤器。 新建python packages-命名固定 templatetags,在templatetags中自定义过滤器的文件


首先使用load标签引入模块

{%load filters%}


自定义的过滤器函数,至少有一个参数,最多两个

模板注释

单行注释

{# 注释内容 #}

多行注释

{% comment %}注释内容
{% endcomment %}

模板注释在开发者模式下看不到注释代码,而html注释(<!---->)可以看到

模板继承

模板继承和类的继承含义是一样的,主要是为了提高代码重用
典型应用:网站的头部、尾部信息。

父模板
如果发现在多个模板中某些内容相同,那就应该把这段内容定义到父模板中。
标签block:用于在父模板中预留区域,留给子模板填充差异性的内容,名字不能相同。 为了更好的可读性,建议给endblock标签写上名字,这个名字与对应的block名字相同。父模板中也可以使用上下文中传递过来的数据。

{%block 名称%}
预留区域,可以编写默认内容,也可以没有默认内容
{%endblock  名称%}



子模板
标签extends:继承,写在子模板文件的第一行。

{% extends "父模板路径"%}


子模版不用填充父模版中的所有预留区域,如果子模版没有填充,则使用父模版定义的默认值。
填充父模板中指定名称的预留区域。

{%block 名称%}
实际填充内容
{{block.super}}用于获取父模板中block的内容
{%endblock 名称%}




HTML转义

模板对上下文传递的字符串进行输出时,会对以下字符自动转义。

小于号< 转换为 &lt;大于号> 转换为 &gt;单引号' 转换为 '双引号" 转换为 &quot;与符号& 转换为 &amp;



要关闭模板上下文字符串的转义:
可以使用

{{ 模板变量|safe}}

也可以使用

{% autoescape off %}模板语言代码
{% endautoescape %}


模板硬编码中的字符串默认不会经过转义,如果需要转义,那需要手动进行转义。

CRSF

Cross Site Request Forgery,译为跨站请求伪造。CSRF指攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全
如果想防止CSRF,首先是重要的信息传递都采用POST方式而不是GET方式,接下来就说POST请求的攻击方式以及在Django中的避免。

django防止csrf的方式:

  1. 默认打开csrf中间件。
  2. 表单post提交数据时加上{% csrf_token %}标签。

    防御原理
    渲染模板文件时在页面生成一个名字叫做csrfmiddlewaretoken的隐藏域。

    服务器交给浏览器保存一个名字为csrftoken的cookie信息。

    提交表单时,两个值都会发给服务器,服务器进行比对,如果一样,则csrf验证通过,否则失败。

验证码

在用户注册、登录页面,为了防止暴力请求,可以加入验证码功能,如果验证码错误,则不需要继续处理,可以减轻业务服务器、数据库服务器的压力。

安装包Pillow3.4.1

pip install Pillow==3.4.1

在booktest/views.py文件中,创建视图verify_code。
提示1:随机生成字符串后存入session中,用于后续判断。
提示2:视图返回mime-type为image/png。

from PIL import Image, ImageDraw, ImageFont
from django.utils.six import BytesIO
...
def verify_code(request):#引入随机函数模块import random#定义变量,用于画面的背景色、宽、高bgcolor = (random.randrange(20, 100), random.randrange(20, 100), 255)width = 100height = 25#创建画面对象im = Image.new('RGB', (width, height), bgcolor)#创建画笔对象draw = ImageDraw.Draw(im)#调用画笔的point()函数绘制噪点for i in range(0, 100):xy = (random.randrange(0, width), random.randrange(0, height))fill = (random.randrange(0, 255), 255, random.randrange(0, 255))draw.point(xy, fill=fill)#定义验证码的备选值str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0'#随机选取4个值作为验证码rand_str = ''for i in range(0, 4):rand_str += str1[random.randrange(0, len(str1))]#构造字体对象,ubuntu的字体路径为“/usr/share/fonts/truetype/freefont”font = ImageFont.truetype('FreeMono.ttf', 23)#构造字体颜色fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))#绘制4个字draw.text((5, 2), rand_str[0], font=font, fill=fontcolor)draw.text((25, 2), rand_str[1], font=font, fill=fontcolor)draw.text((50, 2), rand_str[2], font=font, fill=fontcolor)draw.text((75, 2), rand_str[3], font=font, fill=fontcolor)#释放画笔del draw#存入session,用于做进一步验证request.session['verifycode'] = rand_str#内存文件操作buf = BytesIO()#将图片保存在内存中,文件类型为pngim.save(buf, 'png')#将内存中的图片数据返回给客户端,MIME类型为图片pngreturn HttpResponse(buf.getvalue(), 'image/png')

配置url

url(r'^verify_code/$', views.verify_code),

运行服务

调用验证码
创建视图verify_show。

def verify_show(request):return render(request,'booktest/verify_show.html')

配置url

url(r'^verify_show/$', views.verify_show),

创建verify_show.html。

<html>
<head><title>验证码</title>
</head>
<body>
<form method="post" action="/verify_yz/">{%csrf_token%}<input type="text" name="yzm"><img id="yzm" src="/verify_code/"/><span id="change">看不清,换一个</span><br><input type="submit" value="提交">
</form>
</body>
</html>

运行服务

验证
创建视图verify_yz。

def verify_yz(request):yzm=request.POST.get('yzm')verifycode=request.session['verifycode']response=HttpResponse('no')if yzm==verifycode:response=HttpResponse('ok')return response

配置url。

url(r'^verify_yz/$', views.verify_yz),


反向解析

当某一个url配置的地址发生变化时,页面上使用反向解析生成地址的位置不需要发生变化
根据url 正则表达式的配置动态的生成url
在项目urls中包含具体应用的urls文件时指定namespace

在应用的urls中配置是指定name

在模板文件中使用时,格式如下:

{% url 'namespace名字:name' %} 例如{% url 'booktest:fan2'%}

带位置参数:

{% url 'namespace名字:name' 参数 %} 例如{% url 'booktest:fan2' 1%}




带关键字参数:

{% url 'namespace名字:name' 关键字参数 %} 例如{% url 'booktest:fan2' id=1 %}




在重定向的时候使用反向解析:
from django.core.urlresolvers import reverse
无参数:
reverse(‘namespace名字:name名字’)
如果有位置参数
reverse(‘namespace名字:name名字’, args = 位置参数元组)
如果有关键字参数
reverse(‘namespace名字:name名字’, kwargs=字典)

Django(一)-学习笔记整理相关推荐

  1. 【mysql学习笔记整理】

    /*mysql学习笔记整理*/ /*常用的数据库操作对象*/ #库的操作 #创建 #数据库的创建 USE mysql; CREATE DATABASE db_x; #删除 #删除数据库 DROP DA ...

  2. Deep Learning(深度学习)学习笔记整理系列之(五)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  3. Deep Learning(深度学习)学习笔记整理系列之(二)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  4. python eval 入门_Python学习笔记整理3之输入输出、python eval函数

    Python学习笔记整理3之输入输出.python eval函数 来源:中文源码网    浏览: 次    日期:2018年9月2日 Python学习笔记整理3之输入输出.python eval函数 ...

  5. Deep Learning(深度学习)学习笔记整理系列之(八)

     Deep Learning(深度学习)学习笔记整理系列之(八) 分类: Deep Learning 机器学习 Linux驱动2013-04-10 11:4257652人阅读评论(25)收藏举报 ...

  6. Deep Learning(深度学习)学习笔记整理系列三

    Deep Learning(深度学习)学习笔记整理系列 声明: 1)该Deep Learning的学习系列是整理自网上很大牛和机器学习专家所无私奉献的资料的.具体引用的资料请看参考文献.具体的版本声明 ...

  7. Deep Learning(深度学习)学习笔记整理(二)

    本文整理了网上几位大牛的博客,详细地讲解了CNN的基础结构与核心思想,欢迎交流 [1]Deep learning简介 [2]Deep Learning训练过程 [3]Deep Learning模型之: ...

  8. java反射 pdf_java反射学习笔记整理.pdf

    java反射学习笔记整理.pdf 还剩 15页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,很抱歉,此页已超出免费预览范围啦! 如果喜欢就下载吧,价低环保! 内容要点: Java 反射笔记 ...

  9. 天猫整站SSM-后台分类管理-增加(做个人学习笔记整理用)

    天猫整站SSM-后台分类管理-增加(做个人学习笔记整理用) CategoryController: request.getSession().getServletContext()// 获取的是pag ...

  10. 天猫整站SSM-分页-总结(做个人学习笔记整理用)

    天猫整站SSM-分页-herf(做个人学习笔记整理用) 先写Page.java package com.how2java.tmall.util;public class Page {private i ...

最新文章

  1. 检测到在集成的托管管道模式下不适用的 ASP.NET 设置。
  2. windows7下消除快捷键箭头的方法
  3. python父类的类成员怎么定义_python如何找到哪些父类定义子对象的方法
  4. mysal向一个无法连接的网络尝试了一个套接字操作 0.0.3.235_第十二章 Java网络编程(3)——套接字(上)...
  5. MarshalHelper
  6. 目前市场上的电脑一体机从计算机种类,一体机电脑与普通电脑的区别
  7. 一个整数转换成字符串(C/C++自己写的算法)
  8. 云专网和云专线的区别_传统IDC行业与云计算的区别?
  9. C/C++中使用可变参数
  10. python手动抛出异常
  11. 敬业签桌面便签软件:该openid已被使用,无法绑定!(适用QQ微信互联登录解绑)
  12. PS仿制图章工具、油桶工具、渐变
  13. python df 合并_pandas两个df数据如何合并?
  14. MySQL系列11—简单优化
  15. 如何修改ftp服务器密码,ftp密码,3种修改ftp密码的方法
  16. 计算机网络管理员绩效考核,网络工程师专业考核方案
  17. for和while循环
  18. typecho本地上传头像_用ProGet搭建本地私有NuGet仓库
  19. 网易数据治理工具产品实践
  20. git入门(msysgit图文安装)

热门文章

  1. 【1+X】易用性测试
  2. Linux系统中如何彻底隐藏一个TCP连接?
  3. 献礼国庆 | 便民出行连成网 绿色发展心相通
  4. BLOG系统设计文档
  5. 金蝶云星空与旺店通·企业版对接集成其他出库查询打通创建其他出库单
  6. UVM简单验证平台从0到1
  7. python文字小游戏大全_教你如何用Python写一个小游戏
  8. 计算机组成原理试卷分析,计算机组成原理试卷分析.doc
  9. 生成openVPN客户端配置的shell脚本
  10. python剪辑视频_你知道吗?Python也可以剪辑视频!