目录
2020-01-13 22:45:36 星期一
2020-01-29 22:01:39 星期三
2020-02-11 23:57 星期二
常见的web框架MVC模型:
-
MVC模型的简介:
MVC(Model View Controller)的中文名称叫做模型视图控制器模型,就是因为它的英文名字太流行了,中文名字反而被忽略了。它诞生于20世纪80年代,原本是为桌面应用程序建立起来的一个框架,现在反而在Web应用中大放异彩(其实也可以把B/S认为是C/S的瘦化结构),MVC框架的目的是通过控制器C将模型M(代表的是业务数据和业务逻辑)和视图V(人机交互的界面)实现代码分离,从而使同一个逻辑或行为或数据可以具有不同的表现形式,或者是同样的应用逻辑共享相同、不同视图。比如,可以在IE浏览器访问某应用网站(页面格式遵守HTML标准),也可以用于手机访问。
简单点说就是和算法中的分而治之有点像。将一个功能分成不同的模块进行操作,最后在进行并,也就是耦合。
-
MVC模型的原理:
下面这个就是MVC工作的基本原理图:
浏览器(客户端)发送请求给 C 控制器,控制器将接收数据后,通过 M 将数据存放到数据库中并将存储的结果直接返回给 C , C 然后给 v 视图发送命令, v 将展示视图的HTML返回给 c 控制器,控制器最后再将返回来的命令直接传给浏览器进行展示。综上:MVC模块中各个器件的工作原理也都清晰明了:
C:控制器。相当于人的大脑,进行命令的处理和结果的返回。与M和V进行交互。
V:视图器。展示的html页面全部都交给它进行。
M:模板器。和数据库进行交互。
MVT模型
-
MVT模型的简介
MVT模型和传统的MVC模型实际上是一样的。只是在创建Django这个框架的时候,把他改成了MVT模型。但是实际上的一些功能的组成是和MVC是一样的。在这里也不过多的讲述。
-
MVT模型的原理:
下面的图就是MVT模型工作的基本原理
浏览器发送请求的命令给V视图,视图v接受到数据后交给M进行和数据库的交互。模块M将数据存储到数据库之后,将存储的结果和请求一并发给V表示已经存储完成了。然后v将接受到的指令发给T模块说要展示给用户看,然后模块T接受到指令后返回相应的html给模块V,最后模块V在将返回的html返回给用户进行展示。整个过程其实和MVC的如出一辙,只不过就是模块的名称换了。MVT模块中的各个器件的工作原理:
M :和在MVC中一样还是用于和数据库的交互
V :控制器的作用。用于和用户进行命令的发送和接收。主要是与用户进行交互
T:就是在MVC中视图的作用。存储html的页面。需要时进行展示
Django
- Django官方文档: https://www.djangoproject.com/
- Django2.0开发文档: https://docs.djangoproject.com/zh-hans/2.0/
虚拟环境
-
什么是虚拟环境
如果一台机器上面又好几个不同的软件需要不同的环境来运行,而后面的环境里面的包可能会将前面所使用的包里面的进行覆盖,然后就造成了软件不能够运行的情况,这样的时候虚拟环境就派上了用场。
虚拟环境就是直接将原来的原环境进行复制,后面再需要添加一些包的时候再进行添加,但是与整个环境是隔离开来的。对各个环境之间互相都不影响。这就是创建虚拟环境的好处。
-
创建虚拟环境
-
安装虚拟环境的命令:
-
安装虚拟环境
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 virtualenvs (虚拟环境的名字)
进入虚拟环境后,所有安装的包均在虚拟环境下的python文件夹中 -
退出虚拟环境
deactivate
直接就可以退出当前的虚拟环境 -
查看当前所有的虚拟环境
workon+空格+Table按两下就能显示出所有的虚拟环境 -
删除虚拟环境
rmvirtualenv(虚拟环境的名称)
-
- 虚拟环境中安装包的常见命令:
-
安装指定版本的包或者软件:
pip install (包的名字)==(版本号) 例如:pip install Django==2.0
(值得注意的是:不能使用 sudo pip install Django==2.0 sudo代表着超级管理的意思,这样会直接将包安装到真实的主机环境中间去)
apt-get install (软件) 例如:apt-get install mysql
(这个安装命令是直接安装软件的,不像前面一个pip install (包的名字)==(版本号)一样是需要依赖于python环境下才能进行安装的。这个命令直接在虚拟环境下安装想要使用的软件,不需要依赖于任何的环境)
-
查看当前虚拟环境安装的所有包的命令
pip list 或者 pip freeze
-
创建Django项目
-
创建Django项目:
django-admin startproject(项目的名称)
manage.py:
主要是用来创建一些应用的系统式文件init.py:
初始化文件.告诉使用者这是一个python的包settings.py:
项目的配置文件urls.py:
主要是配置路由url地址wsgi.py:
服务器与django交互的入口
-
创建Django应用:
python manage.py startapp (应用的名称)
admin.py:
这是后台进行管理的文件,同过这个文件进行后台管理。apps.py:
当前app的配置信息,在Django1.9后自动生成,一般情况下无须进行修改M,V,T,:
mvt三兄弟前面有就不在这里细说了
-
项目与应用的联系:
在项目的setting.py文件中配置前面已经创建过的应用,使得项目和应用产生联系
2020-01-13 22:45:36 星期一
ORM框架:
O(object 类,对象),R(relation 关系),M(mapping 映射)
ORM也就是根据O模板中的类生成相应的表直接映射到数据库中进行相应的操作
Django中内置了ORM框架。直接可以通过模型类映射到数据库中的表,操作数据表,从而不在需要使用SQL语句进行操作。
ORM还可以根据设计的类生成数据库中的表
模型类生成表
这里只作简单得介绍,具体得看开发文档中的模型类即可
-
Django1.8.2开发文档模型类:
https://docs.djangoproject.com/zh-hans/2.0/intro/overview/ -
先在model.py文件中创建模型类:
模型类中的具体细节后面在讲。先在model.py文件中创建模型类。
-
生成迁移文件
python manage.py makemigrations这个样子表示迁移文件生成成功。 生成的迁移文件直接放在migrations的文件夹下。
迁移文件的内容# Generated by Django 2.0 on 2020-01-14 10:48 from django.db import migrations, models class Migration(migrations.Migration): initial = True dependencies = [ ] operations = [ migrations.CreateModel( name='BookInfor', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('btitle', models.CharField(max_length=20)), ('bup_data', models.DateField()), ], ), ] #迁移文件中主要是类似于sql语句一样的,将创建的模型类直接变成相应的语句一样
- 执行迁移生成表
python manage.py migrate
这样就表明将迁移文件生成了表
Django后台管理
- 本地化
本地化需要执行的就是修改 所在的地区和时间
在项目配置的setting.py目录中进行修改
如图所示:
Asia/Shanhai: 表示使用上海时区的时间作为后台管理的时间
en-hans: 表示使用汉字作为语言文字
- 创建超级管理员
输入命令:
python manage.py createsuperuser
输入之后按照要求填写
用户名:
邮箱:
密码:
就可以创建超级用户
-
登录管理员账户
127.0.0.1:8000/admin
后面加上admin就能进入管理员登录页面进行登录
输入创建的用户和密码就能就行登录
-
增删改查
后台管理的操作还是比较直白和简单的。直接操作就行。登录后看不到数据表中的操作
只有用户组的(可以进行注册用户删除用户等等的操作)
在admin中注册
这里需要在前面从应用中的models模块中导入两个模型类
就可以看到数据库中的表直接的展示在了后台管理之中后台展示
-
自定义管理页面
想要在后台中显示出表中的信息,而不是直接的一本书,可以自定义显示页面
admin中可以直接写两个模型管理类,并将要显示的内容直接放在列表中
然后注册模型类的时候,在模型类的后面加上注册的模型管理就行效果显示:
而不是直接展示固定的书名了。书籍有关的信息都可以自己随心所欲的展示.
视图函数的使用
-
视图函数基本的使用规则
视图函数的使用基本的套路:
- 视图函数配置
- 项目urls的配置:
urlpatterns: 是所有url地址的集合。整个项目最先就是到这个地方进行地址匹配搜索。
path(): 最前面一个参数是正则表达式进行匹配。匹配上了后就执行后面的include函数。找到应用中的url地址
-
应用url的配置:
应用的url的写法和项目的写法都是一样的,就不再具体叙述。
-
视图函数
视图函数得配置如图:
这里知识简单的讲解一下Django运行的大概模式,后面会详细讲解视图的一些函数。关于视图函数:
视图函数必须有一个参数request,进行响应的请求后,需要返回一个对象。给浏览器进行展示。
- 项目urls的配置:
模板的使用
- 创建模板文件夹
在根目录下创建的模板文件夹,用来装所有的模板文件。为了区分哪一个应用的模板,再在里面创建应用的就行。一般而言开发都是这样做的。
-
配置模板文件
模板文件的配置在项目的settting.py文件下面找到templates列表
重点在DIRS路径配置里面,别的暂时不需要进行使用。路径
直接将模板所在的路径放到里面去就行了,但是这样会导致一个问题就是一旦将模板移除了这个路径,路径一旦改变,项目可能就跑不起来了。所以在Django中的setting.py文件的最前面直接将BASE_DIR用来存储当前项目的路径,所以无论项目的路径怎么去变,都能够在第一时间直接去导出来。所以在配置模板文件的时候直接在后面拼接就行。
setting.py文件中的template配置
- 使用模板文件
Django中直接封装了一个render函数用来进行模板里面的一系列的操作
render函数的原理- 加载模板文件
- 进行参数传递
- 进行模板渲染
- 返回给浏览器
from django.shortcuts import render # Create your views here. from django.template import loader,RequestContext from django.http import HttpResponse #定义index函数 def index(request): #使用模板文件 # 1.加载文件,返回模板对象 temp = loader.get_template('index.html') # 2.定义模板上下文给模板传文件 context = RequestContext(request,{}) # 3.进行模板渲染 huao_html = temp.render(context) # 4.返回给浏览器 return HttpResponse(huao_html)
- 直接使用render函数
最终的效果都是一样的。from django.shortcuts import render # Create your views here. #定义index函数 def index(request): return render(request,'index.html')
通过python shell直接操模板中映射的数据库中的数据表
-
理解
django 中的数据表是通过模板然后迁移到数据库中的,并不需要写sql语句,主要的采用的是ORM框架进行映射。直接写模板类就能生成对应的数据表。所在可以在shell中数理化模板类对象,对类对象进行增删改查,复制等一系列的操作。下面进行演示如何使用shell对数据表进行操作
- 常用的命令
-
数据插入
进入shell终端: python manage.py shell (在虚拟环境的项目下输入命令)
书写的格式和代码差不多。
b1实例化Bookinfor对象后调用对象属性进行复制
最后使用命令 b1.save() 进行保存
在数据库中查看:
直接就添加进去了。(最后一定要进行保存不然写入不进去) -
数据读取
演示:
Bookinfor.objects.get(book_id=1)
这个命令是返回一个bookinfor的对象 b1接收了之后就能够查看这个对象中的所有属性值,也能够进行更改。最后只要保存了就行。我们再次查看数据表,应该可以看到《三国演义》能够变成《白鹿原》.
数据库中查看
可以看到book_id为1的书名改为了《白鹿原》
-
连接mysql数据库
-
连接数据库
连接mysql数据库也是在setting.py文件中进行设置。连接数据库之前必须在项目所在的目录下的__init__.py文件中对MySQL进行注册
注册的代码如图:设置的选项:
ENGINE: 这是Django中支持的数据库,有MySQL,Oracle等等都是支持的
NAME: 连接数据库的名字。这需要提前在数据库中进行创建
USER: 连接数据库的用户名
PASSWORD: 该用户名下对应的密码
HOST: 该数据库所在的主机IP地址
PORT: MySQL数据库对应的端口地址默认是3306示例:
# Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases DATABASES = { 'default': { 'ENGINE':'django.db.backends.mysql', 'NAME':'book', 'USER':'root', 'PASSWORD':'mysql', 'HOST':'127.0.0.1', 'PROT':'3306', } }
重定向
- 重定向的意思:
重定向的意思就是说浏览器里面指定访问的一个url地址,去网站服务器里面访问后,
网站的服务器又指向浏览器中另外的一个地址,然后浏览器再去访问网站服务器的那个另外的地址。
这样形成的叫做网页重定向。
- 重定向的解释图
- 具体的代码示例:
- HttpResponseRedirect
这样就能够保证在点击添加的时候,超链接执行完这个函数后直接访问 /index 地址。#添加书籍的函数 def add_book(request): b = Bookinfor() b.book_name = '三国演义' b.save() return HttpResponseRedirect('/index')
然后再次执行 /index 的时候就相当于刷新了。
只是现在都是使用redirect 进行网页的重定向。 - Redirect
代码演示:
两者的功能是一样的。#删除书籍的函数 def remove_book(request,bookid): book = Bookinfor.objects.get(book_id=bookid) book.delete() return redirect('/index')
- HttpResponseRedirect
字段的类型和选项
- 字段的属性
-
模型类属性命名的限制:
- 不能够是python中的关键字
- 不能够有连续两个下划线,这是由django官方的查询机制决定的
- 定义的时候需要指定字段类型才能够生效(属性名=models.字段类型(选项))
-
常见的字段类型:
使用字段类型的时候需要导入django.db.models.
一般情况下是直接就导入了的。
-
类型 | 描述 |
---|---|
AutoField | 自动增长的IntegerField,通常情况下不用进行指点,Django会自动为其创建自动增长的ID |
BooleanField | 布尔字段,Ture or False |
NullBooleanField | 支持Null,Ture,False三种类型 |
CharField | 字符串(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) | 这是日期类型: 1:参数auto_now 表示每次保存对象的时候,自动设置位字段当前的时间,用于最后一次修改的时间戳。 2:参数auto_now_add表示当前对象第一次创建的时候的时间戳,用于创建的时间戳,都是使用当前日期,默认都是位False 3:参数suto_now 和参数auto_now_add是相互排斥的,一起组合将会发生错误 |
TimeField | 时间参数同DateField |
DateTimeField | 日期时间,参数同DateField |
常见的字段类型就是这,更多的见开发文档就行,开发文档写的还是很详细的。
- 字段的选项
选项的作用就是实现对字段的约束
选项名 | 描述 |
---|---|
default | 设值默认值 |
primary_key | 设置主键的。默认值位False。一般是在AutoField的选项中使用 |
unique | 这是数据库中唯一性的标识。默认值都是Fales。若为Ture则表示这个字段在表中必须具有唯一值,不能够重复 |
db_index | 若位Ture,则会在表中位字段创建字段索引,默认值是False |
db_column | 主要的作用是自定义字段的名称。如果没有指定则使用模型中的。如果另外指定则使用指定的属性的名称 |
null | 若为True,则表示允许为空。默认值是False |
blank | 若为True,则表示允许字段为空白,在表格的时候可以不用填写就能够添加。默认值是False |
对比: null是数据库的范畴的范围概念,blank是后台管理页面表单验证范畴的。
经验: 如果添加的选项不影响表的结构,则不需要重新做迁移。例如:default 和blank不影响表的结构,则不需要重新迁移。
更多的见开发文档.
查询
-
修改mysql日志文件
修改mysql的日志文件,就是让其产生mysql.log文件,让其对每一次对数据库的操作都能够看的清楚1. 使用下面的命令打开mysql的配置文件,删除其68,69行。 /etc/mysql/mysql.conf.d/mysql.cnf 这是数据库配置文件的路径。可以用多种方式进行打开。这里需要管理员的最高权限。直接sudo进入就行 2. 删除保存了以后直接从新启动服务就行 service mysqld restart 表示重启mysql服务 3. 打开mysql.log日志文件 路径:/var/log/mysql/mysql.log是mysql.log文件所在的路径 打开方式: tail -f /var/log/mysql/mysql.log 这所有的操作都是在超级管理员的模式下进行的(sudo)
截图:
这是打开后的文件,直接注释掉68,69行就行,然后保存文件
保存文件后重新启动服务文件,可以看到mysql.log文件已将展示出来了。
打开日志文件 sudo tail -f /var/log/mysql/mysql.log
空格一直都是在最后一行。
在客户端连接上MySQL数据库后就会显示如图的
每做一部操作都可以看到mysql日志文件中有具体的显示操作例如在shell中实例化模型对象
在日志中就会出现响应的sql语句
-
查询函数
通过模型类.objects.(函数名)就可以直接通过模型类操作数据库中数据表的查询函数名 功能 返回值 说明 get 返回满足条件的数据(有且只有一个) 返回值是一个模型对象 参数中写的是查询条件:1. 如果查询到多条数据则抛出MultipleObjectsRetuened2.查询不到数据,则抛出异常DoesNotExiist all 返回模型类对应表格中所有的对象 返回值是该对象的集合 查询集 filter 返回满足条件的数据 返回值也是QuerySet类型 参数写查询条件 exclude 返回不满足条件的数据 返回值也是QuerySet 参数写查询条件 order_by 对查询的结果进行排序 返回值是QuerySet 参数中写根据那些字段进行排序 1. get
get函数只能返回一个符合条件的对象,查不到或者多个一样的都会报错
(查询数据库中没有的)
返回的结果:(没有找到这个符合条件的)
2. all
返回的是满足该条件的集合(QuerySet)我们叫做查询集,可以进行遍历。可以看到的是里面有6个Book模型对象
3.filter
filter里面写的也是查询条件,返回的是符合条件的对象集,与get的区别就在于它能返回多个对象,而get只能返回一个符合条件的对象。
使用:
Book.objects.filter(查询条件)4.exclude
返回的是不符合条件的对象集。使用方法和上面的一样
使用:
Book.objects.exclude(book_id=2) 查询书籍不包含书籍编号为2的书籍的信息5.order_by
对返回的对象集进行排序
使用:
Book.objects.all().order_by(‘id’) 将查询的结果通过id进行从小到大的排列
Book.objects.all().order_by(’-id’) 将查询的结果通过id进行从大到小的排列
-
查询条件
1. 使用方法:
使用之前还是需要导入模块
from bookimfor.models import Book
属性名称__(双下划线)加上查询条件
Book.objects.filter(book_id__in=[1,2,3]) 表示查询书籍编号在1,2,3这些范围的书籍2. 查询条件
条件 使用案例 说明 结果 范围查询 in Book.objects.filter(book_id__in=[1,2,3,4,5]) 查询书籍编号在1,2,3,4,5之间的书籍 QuerySet [<Book: Book object (1)>, <Book: Book object (2)>, <Book: Book object (3)>, <Book: Book object (4)>]> gt(great than) Book.objects.filter(book_id__gt=3) 查询书籍编号大于3的书籍的信息 QuerySet [<Book: Book object (4)>, <Book: Book object (5)>, <Book: Book object (6)>]> lt(less than) Book.objects.filter(book_id__lt=3) 查询书籍编号小于3的书籍信息 QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]> gte(great than equal) Book.objects.filter(book_id__gte=3) 查询书籍大于等于3的书籍信息 QuerySet [<Book: Book object (3)>, <Book: Book object (4)>, <Book: Book object (5)>, <Book: Book object (6)>]> lte(less than equal) Book.objects.filter(book_id__lte=3) 查询书籍小于等于3的书籍的信息 QuerySet [<Book: Book object (1)>, <Book: Book object (2)>, <Book: Book object (3)>]> 日期查询: year Book.objects.filter(bup_date__year=1980) 查询1980年出版的图书 数据库中没有这一个属性就不做查询 日期查询 Book.objects.filter(bup_date__gt=date(1980,09,01) 查询1980,09,01之后出版的书籍。 只需要把这个转换成为时间类型就可以直接比较大小 模糊查询 contains Book.objects.filter(book_name__contains=‘国’) 查询书籍名中包含国字的书籍信息 QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]> startswith Book.objects.filter(book_name__startswith=‘国’) 查询书籍中以国字开头的书籍的信息 QuerySet []> endswith Book.objects.filter(book_name__endswith=‘三’) 查询书籍中以三字结尾的书籍的信息 QuerySet []> 判等查询 exact Book.objects.filter(book_id__exact=1)(和省略exact的效果是一样的) 查询书籍编号为1的书籍的信息 QuerySet [<Book: Book object (1)>]> 空查询 isnull Book.objects.filter(book_name__isnull=True) 查询书籍名为空的书籍的信息 QuerySet []>
F函数
-
说明
F函数主要解决的问题是属性之间的比较的问题 -
使用示例
使用之前要从模块中导入F函数
from django.db.models import F使用案例 说明 结果 Book.objects.filter(book_add__gt=F(‘book_name’)) 查询书籍中评论量大于书籍名的书籍信息 QuerySet [<Book: Book object (1)>, <Book: Book object (2)>, <Book: Book object (4)>, <Book: Book object (5)>]> Book.objects.filter(book_add__gt=F(‘book_name’)*2) 查询书籍中评论量大于书籍名两倍的书籍的信息(直接在后面✖2就行) QuerySet []>
Q函数
-
说明
Q函数主要是解决属性之间的**与(&),或(|),非(~)**的问题
使用之前依旧是要导入Q函数
from django.db.models import Q -
使用示例
使用案例 说明 结果 关系 Book.objects.filter(Q(book_id__lt=3)&Q(book_name__contains=‘国’)) 查询书籍编号小于3且书籍名里面包含国的书籍的信息 QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]> 与(&) Book.objects.filter(Q(book_id__lt=3)(或)Q(book_name__contains=‘红楼梦’)) 查询书籍编号小于3或者书籍名包含红楼梦的图书的信息 QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]> 或 Book.objects.filter(~Q(book_id=3)) 查询书籍编号不为3的书籍的信息 QuerySet [<Book: Book object (1)>, <Book: Book object (2)>, <Book: Book object (4)>, <Book: Book object (5)>, <Book: Book object (6)>]> 非
聚合函数
-
说明
- 常见的聚合函数有 Count,Max,Min,Sum,Avg这五个
- 使用这些函数需要aggregate来调用。 返回值是一个字典
- 从下面返回的那些结果可以看见,字典的键的命名是属性名+聚合函数名
-
使用示例
函数 使用示例 说明 结果 Max Book.objects.all().aggregate(Max(‘book_id’)) 查询书籍编号中最大的一个 {‘book_id__max’: 6} Min Book.objects.all().aggregate(Min(‘book_id’)) 查询书籍编号中最小的一个 {‘book_id__min’: 1} Count Book.objects.all().aggregate(Count(‘book_id’)) 按照书籍编号计算一共有多少本书 book_id__count’: 6} Avg Book.objects.all().aggregate(Avg(‘book_id’)) 计算书籍编号的平均值 {‘book_id__avg’: Decimal(‘3.5000’)} Sum Book.objects.all().aggregate(Sum(‘book_id’)) 计算所有书籍编号的和 {‘book_id__sum’: Decimal(‘21’)} 另外的一个函数不是属于聚合函数的,和ordey_by差不多的类型
函数 使用示例 说明 结果 count Book.objects.filter(book_id__gte=3).count() 计算书籍编号大于等于3的有多少 4 -
两者的区别
- 函数是小写。
- 返回值只是一个数字,不是字典
查询集(QuerySet)
all,filter,exclude,order_by调用这些函数会产生一个查询集
QuerySet类对象可以继续调用上面所有函数
-
查询集特性
- 惰性: 所有的查询只有在真正用到该数据的时候才会真正的进行查询。否则不会进行真正的查询
- 缓存: 如果两次使用查询集相同的话,第二次使用的查询集会直接使用第一次查询完成后缓存的结果,不会进行真正的第二次查询
-
限制查询集
如果一个查询集的结果很多,而不是每一个对象都是想要的话,可以使用下标或切片的方法进行限制查询集的查询。对一个查询集进行切片后会产生一个新的查询集
切片的下标不允许为负数
-
取出查询集数据的方法
Python 3.5.1+ (default, Mar 30 2016, 22:46:26) [GCC 5.3.1 20160330] on linux Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> from bookimfor.models import Book >>> ids = Book.objects.filter(book_id__gte=1) >>> id = ids[0:3] >>> type(id) <class 'django.db.models.query.QuerySet'> >>> id[0] <Book: Book object (1)> >>>
直接当列表进行使用就行。按照序号进行提取
注意:
- b[0]如果不存在,会报出索引异常(IndexError)
- b[0:3].get()如果不存在,会爆出DoesNotExist
- 可以用exists函数判断查询集中是否有数据
True表示有数据id.exists() True >>> id=ids[0:0] >>> id.exists() False >>>
False表示没有数据
模型类关系
-
模型类关系
关系 例句 使用对象 一对一 models.OneToOneField() 放在关系的哪个类中都可以 一对多 models.Foreigney() 放在关系的多的哪一个类中 多对多 models.ManyToManyField() 多对多放在哪个类中都可以 这个和数据库中讲的关系是一样的
这里再创建模型类中的属性的时候进行使用就行
-
说明:
在一对多的关系中,一对应的类我们叫做一类,多对应的类我们叫做多类。我们把多类中建立关联的类属性叫做关联类属性。关联类的查询我们叫做关联查询
-
图解:
-
通过模型类查询
在查询的过程中要分清楚是一类还是多类。
查询对象 被查询对象 示例 说明 结果 一类 多类 Book.objects.filter(hero__id__gt=3) 查询英雄编号大于3的所属于的书籍信息 QuerySet [<Book: Book object (3)>, <Book: Book object (4)>, <Book: Book object (5)>, <Book: Book object (3)>]> 多类 一类 Hero.objects.filter(fid__book_id=1) 查询书籍编号为1中所有的英雄 QuerySet [<Hero: Hero object (1)>, <Hero: Hero object (3)>]> 由此可见查询的方法:
-
查询什么就以什么类在最外面。****的书籍信息,就是Book.objects啥啥啥的。****的英雄信息就是Hero某某某的。看最后的落脚点
-
多查一
多类名.objects.查询函数(关联条件属性__(双下划线)一类属性名__查询条件) -
一查多
一类名.objects.查询函数(多类名(小写)__多类属性名__查询条件)
-
值得注意:
- 通过模型类实例对象来关联查询的时候,要哪个类就用哪个类查
- 写关联查询条件的时候如果类中有关联属性,则直接写关联属性。如果没有关联属性则写对应的类名
插入,删除,更新
-
说明:
调用模型类的save方法就能够完成对模型类对应的数据表插入和更新操作
调用模型类的delete方法就能够完成对模型类对应的数据表的删除操作代码演示:
-
save方法(插入和更新)。
(py3) python@ubuntu:~/Desktop/项目/py3+django2.0/书籍增删$ python manage.py shell Python 3.5.1+ (default, Mar 30 2016, 22:46:26) [GCC 5.3.1 20160330] on linux Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> from bookimfor.models import Book >>> books = Book.objects.get(book_id=1) >>> books.book_name '三国演义' >>> books.book_name='水浒传' >>> books.save() >>>
运行结果:
编号为1的书籍的名字已经发生了更新,更新为水浒传 -
删除方法(delete)
books = Book.objects.get(book_id=1) >>> books.delete() (3, {'bookimfor.Book': 1, 'bookimfor.Hero': 2})
运行结果:
书籍表中
英雄表中
可以看到书籍表中,编号为1的书籍已经删除。英雄表中和编号为1的书籍相关的英雄也已经删除。
-
自关联
-
说明:
自关联的意思就是说,使用自身的主键同时又做外键进行自关联。自关联的作用就是能够将有联系的多张表合成为一张表,从而节省空间。 -
代码演示:
自关联是一个特殊的一对多的关系
所以还是使用ForeignKey做外键举个例子:
上面的代码就是使用的这个省市区的例子,采取自关联的。
管理器
-
说明
模型类.objects.查询函数 中的objects是什么呢,这个就是管理器。objects是django自动生成的管理器对象,通过这个管理器对象可以实现对数据的查询
type(Book.objects) <class 'django.db.models.manager.Manager'>
查看objects的类型,可以看到objects是models.Manager的一个对象
-
作用
管理器的作用
-
改变查询集的结果
-
添加额外的方法(原来里面没有进行封装的方法,可以自己添加着进行使用)
-
-
改变查询集的结果:
改变查询集的结果说白了就是让重写原来的查询函数,让它又特定的功能。只不过是将它封装在管理器类中。
代码演示:
class BookInforManage(models.Manager): #重写父类的方法 def all(self): books = super().all() return books.filter(book_id__gt='4')
继承父类的all方法后,然后进行改写,将满足条件的封装进来.
然后可以看到,再次调用all方法的时候,就不会将所有的对象展现出来了,只会将满足条件的筛选出来,这里是书籍编号大于4的筛选出来。
运行结果:
可以看到再次调用all方法的时候,出现的并不是所有的对象,而是大于4的对象的集合。 -
添加额外的方法:
代码演示:
class BookInforManage(models.Manager): #从写父类的方法 def all(self): books = super().all() return books.filter(book_id__gt='4') def create_objects(self,bname,badd): models_book = self.model() # 实时获取使用这个管理器类的模型类对象。这样就不管实例化这个类的对象怎么改,都可直接获取到。 b = models_book() b.book_name = bname b.book_add = badd b.save() return b
写了一个添加的新方法create_objects()。在这个方法中添加书籍并保存。
运行结果:
添加成功后查看数据库中数据是否已经进去
可以看到数据添加成功。 -
创建模型管理器类对象
创建模型管理器后,原来自动生成的objects对象就不再被使用了
class Book(models.Model): book_id = models.AutoField(primary_key=True) book_name = models.CharField(max_length=20) book_add = models.CharField(max_length=10) #自定义管理器对象 supervisor = models.Manager()
创建模型管理器对象可以在模型类中实例化models.Manager对象就行
在shell终端中查看情况:
可以看到Book中已经没有这个objects对象了,原因就是因为已经自己定义了另外一个models.Manager类对象。
查看对象中的所有信息,只需要调用新的objects对象就可以了
从新定义管理器对象后,需要从新进入shell中进行查询,才会出现上面的结果。
但是一般的情况下不会这样进行。因为这样会导致代码量加大。也不方便后面进行维护
所以我们会直接定义一个管理器类,在这个类里面添加自己的额外的方法。 -
管理器类
一般我们会另外创建一个管理器类然后在里面改变查询结果和添加额外的方法,这里先暂时不写,只是说明原理。class BookInforManage(models.Manager): pass # 创建书籍类 class Book(models.Model): book_id = models.AutoField(primary_key=True) book_name = models.CharField(max_length=20) book_add = models.CharField(max_length=10) #自定义管理器对象 supervisor = BookInforManage()
创建管理器类对象后,在Book模型类中实例化了BookInforManage这个类。然后直接调用就行。
shell终端中
在shell终端中可以看到,Book.supervisor已经变成了我们创建的BookInforManage的类型。
元选项
-
说明:
Django中的数据表命名: 应用名小写_模型类名小写这就造成一旦应用名发生了改变后,数据表的名字就会发生改变
所以在django中可以指定表明,无论应用名发生什么改变都不会影响数据表的命名这称之为元选项 :
只需要在模型类中定义一个元类Meta,在里面添加属性db_table就可以指定表名。
-
代码实现
# 创建书籍类 class Book(models.Model): book_id = models.AutoField(primary_key=True) book_name = models.CharField(max_length=20) book_add = models.CharField(max_length=10) # 自定义管理器对象 supervisor = BookInforManage() # 添加原选项 class Meta: db_table = 'bookinfor' #指定模型类的表名
值得注意的就是这个类直接加在模型类后面的。
将文件迁移成功后
查看数据库中的表的名字
原来的bookimfor_book变成了bookinfor。 无论应用名字怎么改变,都不会影响数据库中表的名字这个就是元选项。
视图
-
错误视图
首先来了解开发模式。
开发模式:当setting文件的DEBUG处于True的时候表示处于开发者模式中,页面出现的所有的错误都会非常详细的显示出来,好让开发人员进行调试。
图片中黄色的部分,分别描述了发送的请求,相应的url地址,异常类型,出现异常的位置,python的版本和python中配置的环境路径等。下面就是指出了错误的原因。
框中的两个地方是比较重要的部分。告诉我们这是在某某路径下的view.py文件中,有一个name变量没有被定义,而导致出现异常。
在开发者模式下,将异常显示的非常清楚,一下就能找到问题所在的地方。但是在非开发者模式下就什么信息都没有提示了。
将DEBUG=True变为False
将开发者模式变为非开发者模式
然后再templates里面配置出现错误的模板文件。(这个错误属于500出现的错误所以直接命名)
此时django自带的服务器会直接断开出现异常以为没有指定能够连接的主机,所以为了安全会直接的断开。
指定允许连接的主机后再从新打开会出现。
通配符表示匹配所有的主机地址。然后再次运行服务器。会发现已经没有了详细的信息。而是出现之前配置好的500的页面
这就是对错误页面的配置。出现别的状态码也是一样,大同小异。状态码后面我们再讲。
捕获url参数
- 说明:
进行url捕获的时候,把要捕获的地方设置成为一个正则表达式的分组,这样再进行匹配的时候,Django就会自动把匹配的结果传给后面的视图函数。 - 参数:
-
位置参数:
像上面说的,将匹配的内容直接传给后面视图函数中的参数,而这视图函数中的参数可以是任意的,只要符合python的命名规则就行。这样的叫做位置参数。 -
关键字参数:
关键字参数就是在位置参数的基础上对正则表达式的分组进行命名即可,和我们之前学的正则表达式的命名是一样的,使用的方法也是差不多的。?p<组名>
关键字参数 关键字中的参数必须和正则表达式的组名一致。
-