1. Django ORM
- O(objects):类和对象。
- R(Relation):关系,关系数据库中的表格。
- M(Mapping):映射。
Django ORM框架的功能: - a) 建立模型类和表之间的对应关系,允许我们通过面向对象的方式来操作数据库。
- b) 根据设计的模型类生成数据库中的表格。
- c) 通过方便的配置就可以进行数据库的切换。
2. Django数据库配置
2.1 mysql命令回顾
- 登录mysql数据库: mysql –uroot –p
- 查看有哪些数据库:show databases
- 创建数据库:create database test2 charset=utf8; #切记:指定编码
- 使用数据库:use test2;
- 查看数据库中的表:show tables;
2.2 Django配置使用mysql数据库
修改settings.py中的DATABASES。
sqlite3改为mysql,以及用户名、密码
DATABASES = {
'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
'ENGINE': 'django.db.backends.mysql',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
'NAME': 'xxxx', # 使用的数据库的名字,数据库必须手动创建
'USER': 'root', # 链接mysql的用户名
'PASSWORD': '123', # 用户对应的密码
'HOST': 'localhost', # 指定mysql数据库所在电脑ip
'PORT': 3306, # mysql服务的端口号
}
}
注意:django框架不会自动帮我们生成mysql数据库,所以我们需要自己去创建。
2.3 切换mysql数据库之后不能启动服务器
-
此时会报错:
- django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.Did you install mysqlclient?
-
需要安装操作mysql数据库的包,python2环境和python3环境有以下区别。
- a) python2需要安装mysql-python:
pip install mysql-python - b) python3需要安装pymysql:
pip install pymysql - 可能连接超时,报错WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<pip._vendor.urllib3.connection.HTTPConnection object at 0x7f938d8934a8>: Failed to establish a new connection: [Errno 111] Connection refused',)': /root/pypi/+simple/pymsql/
- pip install pymsql -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
- a) python2需要安装mysql-python:
-
python3中安装好pymysql,需要在test2/init.py中加如下内容:
import pymysql
pymysql.install_as_MySQLdb()
3. 复习案例
-
1)设计模型类并生成表
- a) 设计BookInfo,增加属性bread和bcomment,另外设置软删除标记属性isDelete。
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)
- b) 设计HeroInfo类,增加软删除标记属性isDelete。
- 软删除标记: 删除数据时不做真正的删除,而是把标记数据设置为1表示删除,目的是防止重要的数据丢失。
class HeroInfo(models.Model): '''英雄任务模型类''' # 英雄名 hname = models.CharField(max_length=20) # 性别 hgender = models.BooleanField(default=False) # 备注 hcomment = models.CharField(max_length=200) # 关系属性 hbook = models.ForeignKey('BookInfo', on_delete=models.CASCADE, ) # 删除标记 isDelete = models.BooleanField(default=False)
-
2)编写视图函数并配置URL。
-
3)创建模板文件。
拆解功能: -
2.1) 图书信息展示页。
-
2.1.1) 设计url,通过浏览器访问 http://127.0.0.1:8000/index时显示图书信息页面。
# /test2/urls.py文件中:增加
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include(('booktest.urls', 'booktest'), namespace='booktest')),
]
# 拷贝到booktest应用文件夹中,即/booktest/urls,并修改为:
from django.conf.urls import url
from booktest import views
urlpatterns = [
url(r'^index$', views.index), # 图书信息页面
]
- 2.1.2)设计url对应的视图函数index,查询出所有图书的信息,将这些信息传递给模板文件。
#views.py中:做视图,做完后配置url
from django.shortcuts import render
from booktest.models import BookInfo
# Create your views here.
def index(request):
'''显示图书信息'''
# 1.查询出所有图书的信息
books = BookInfo.objects.all()
# 2.使用模板
return render(request, 'booktest/index.html',{'books':books})
- 3.1) 编写模板文件index.html。
<!--模板文件index.html中进行遍历:-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图书信息</title>
</head>
<body>
<ul>
{% for book in books %}
<li>{{ book.btitle}}</li>
{% endfor %}
</ul>
</body>
</html>
遍历显示出每一本图书的信息并增加新建和删除超链接。
- 2.2)图书信息新增。
- 2.2.1)设计url,通过浏览器访问 http://127.0.0.1:8000/create时向数据库中新增一条图书信息。
# 增加地址,去booktest/urls.py中添加:
from django.conf.urls import url
from booktest import views
urlpatterns = [
url(r'^index$', views.index), # 图书信息页面
url(r'^create$', views.create), # 新增一本图书
]
- 2.2.2) 设计url对应的视图函数create。
def create(request):
'''新增一本图书'''
# 1.创建BookInfo对象
b = BookInfo()
b.btitle = '流星蝴蝶剑'
b.bpub_date = date(1990,1,1) # date需要导入from datetime import date
# 2.保存进数据库
b.save()
# 3.返回应答,返回数据
return HttpResponse('ok')
<!--index.html文件,body中增加:-->
<a href="/create">新增</a>
- 2.3) 页面重定向:服务器不返回页面,而是告诉浏览器再去请求其他的url地址。
# views.py中修改为:
from django.shortcuts import render
from booktest.models import BookInfo
from datetime import date
from django.http import HttpResponse,HttpResponseRedirect
# Create your views here.
def index(request):
'''显示图书信息'''
# 1.查询出所有图书的信息
books = BookInfo.objects.all()
# 2.使用模板
return render(request, 'booktest/index.html',{'books':books})
def create(request):
'''新增一本图书'''
# 1.创建BookInfo对象
b = BookInfo()
b.btitle = '流星蝴蝶剑'
b.bpub_date = date(1990,1,1)
# 2.保存进数据库
b.save()
# 3.返回应答,让浏览器再访问/index
# return HttpResponse('ok')
return HttpResponseRedirect('/index') # 重定向,保持页面URL不变
- 2.4)图书信息删除。
- 2.4.1)设计url,通过浏览器访问 http://127.0.0.1:8000/delete数字删除数据库中对应的一条图书数据。
- 其中数字是点击的图书的id。
# booktest/url中添加:
from django.conf.urls import url
from booktest import views
urlpatterns = [
url(r'^index$', views.index), # 图书信息页面
url(r'^create$', views.create), # 新增一本图书
url(r'^delete(d+)$', views.delete), # 删除点击的图书
]
- 2.4.2) 设计url对应的视图函数delete。
- 获取图书的id,进行删除。
# 在视图views.py中增加delete函数:
def delete(request, bid):
'''删除点击的图书'''
# 1.通过bid获取图书对象
book = BookInfo.objects.get(id=bid)
# 2.删除
book.delete()
# 3.重定向,让浏览器访问/index
# return HttpResponseRedirect('/index') # 可使用redirect替换
return redirect('/index')
4. 字段属性和选项
4.1 模型类属性命名限制
1)不能是python的保留关键字。
2)不允许使用连续的下划线,这是由django的查询方式决定的。
3)定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下:
- 属性名=models.字段类型(选项)
4.2 字段类型
- 使用时需要引入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]) 日期。
- 1)参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false。
- 2)参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false。
- 3)参数auto_now_add和auto_now是相互排斥的,组合将会发生错误。
- TimeField 时间,参数同DateField。
- DateTimeField 日期时间,参数同DateField。
- FileField 上传文件字段。
- ImageField 继承于FileField,对上传的内容进行校验,确保是有效的图片。
4.3 选项
- 通过选项实现对字段的约束,选项如下:
- 选项名 描述
- default 默认值。设置默认值。
- primary_key 若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用。
- unique 如果为True, 这个字段在表中必须有唯一值,默认值是False。
- db_index 若值为True, 则在表中会为此字段创建索引,默认值是False。
- db_column 字段的名称,如果未指定,则使用属性的名称。
- null 如果为True,表示允许为空,默认值是False。
- blank 如果为True,则该字段允许为空白,默认值是False。
- 对比:null是数据库范畴的概念,blank是后台管理页面表单验证范畴的。
经验:
当修改模型类之后,如果添加的选项不影响表的结构,则不需要重新做迁移,商品的选项中default和blank不影响表结构。
- 对比:null是数据库范畴的概念,blank是后台管理页面表单验证范畴的。
5. 查询
5.1 mysql的日志文件
mysql.log是mysql的日志文件,里面记录的对MySQL数据库的操作记录。默认情况下mysql的日志文件没有产生,需要修改mysql的配置文件,步骤如下:
- 1)使用下面的命令打开mysql的配置文件,去除68,69行的注释,然后保存。
- sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
- 2)重启mysql服务,就会产生mysql日志文件。
- sudo service mysql restart
- 3)打开MySQL的日志文件。
- /var/log/mysql/mysql.log 是mysql日志文件所在的位置。
- 使用下面的命令可以实时查看mysql的日志文件:
- sudo tail -f /var/log/mysql/mysql.log
5.2 查询函数
通过模型类.objects属性可以调用如下函数,实现对模型类对应的数据表的查询。
- 函数名 功能 返回值 说明
- get 返回表中满足条件的一条且只能有一条数据。 返回值是一个模型类对象。 参数中写查询条件。
- 1)如果查到多条数据,则抛异常MultipleObjectsReturned。
- 2)查询不到数据,则抛异常:DoesNotExist。
- a)判等 条件名:exact。例:查询编号为1的图书。
- BookInfo.objects.get(id=1)
- all 返回模型类对应表格中的所有数据。 返回值是QuerySet类型 查询集
- all方法示例:查询图书所有信息。
- BookInfo.objects.all()
- all方法示例:查询图书所有信息。
- filter 返回满足条件的数据。 返回值是QuerySet类型 参数写查询条件。
- filter方法示例:
- 条件格式:
- 模型类属性名__条件名=值
- 查询图书评论量为34的图书的信息:
- 条件格式:
- b)模糊查询 例:查询书名包含'传'的图书。contains
- BookInfo.objects.filter(btitle__contains='传') 例:查询书名以'部'结尾的图书 endswith 开头:startswith
- BookInfo.objects.filter(btitle__endswith='部')
- c)空查询 isnull 例:查询书名不为空的图书。isnull
- select * from booktest_bookinfo where btitle is not null;
- BookInfo.objects.filter(btitle__isnull=False)
- d)范围查询 in 例:查询id为1或3或5的图书。
- select * from booktest_bookinfo where id in (1,3,5);
- BookInfo.objects.filter(id__in = [1,3,5])
- e)比较查询 gt(greate than) lt(less than) gte(equal) 大于等于 lte 小于等于 例:查询id大于3的图书。
- Select * from booktest_bookinfo where id>3;
- BookInfo.objects.filter(id__gt=3)
- f)日期查询 例:查询1980年发表的图书。
- BookInfo.objects.filter(bpub_date__year=1980)
- 例:查询1980年1月1日后发表的图书。
- from datetime import date
- BookInfo.objects.filter(bpub_date__gt=date(1980,1,1))
- filter方法示例:
- exclude 返回不满足条件的数据。 返回值是QuerySet类型 参数写查询条件。
- exclude方法示例:查询id不为3的图书信息。
- BookInfo.objects.exclude(id=3)
- exclude方法示例:查询id不为3的图书信息。
- order_by 作用:进行查询结果进行排序。 返回值是QuerySet类型 参数中写根据哪些字段进行排序。
- 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')
- order_by方法示例:查询所有图书的信息,按照id从小到大进行排序。
6. F对象
作用:用于类属性之间的比较。
- 使用之前需要先导入:
- from django.db.models import F
- 例:查询图书阅读量大于评论量图书信息。
- BookInfo.objects.filter(bread__gt=F('bcomment'))
- 例:查询图书阅读量大于2倍评论量图书信息。
- BookInfo.objects.filter(bread__gt=F('bcomment')*2)
7. Q对象
作用:用于查询时条件之间的逻辑关系。not and or,可以对Q对象进行&|~操作。
- 使用之前需要先导入:
- 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))
- 例:查询id大于3或者阅读量大于30的图书的信息。
- BookInfo.objects.filter(Q(id__gt=3)|Q(bread__gt=30))
- 例:查询id不等于3图书的信息。
- BookInfo.objects.filter(~Q(id=3))
8. 聚合函数
作用:对查询结果进行聚合操作。
- sum count avg max min aggregate:调用这个函数来使用聚合。 返回值是一个字典
- 使用前需先导入聚合类:
- from django.db.models import Sum,Count,Max,Min,Avg
- 例:查询所有图书的数目。
- BookInfo.objects.all().aggregate(Count('id'))
- {'id__count': 5}
- BookInfo.objects.all().aggregate(Count('id'))
- 例:查询所有图书阅读量的总和。
- BookInfo.objects.aggregate(Sum('bread'))
- {'bread__sum': 126}
- BookInfo.objects.aggregate(Sum('bread'))
- count函数 返回值是一个数字 作用:统计满足条件数据的数目。
- 例:统计所有图书的数目。
- BookInfo.objects.all().count()
- BookInfo.objects.count()
- 例:统计id大于3的所有图书的数目。
- BookInfo.objects.filter(id__gt=3).count()
小结:
- get:返回一条且只能有一条数据,返回值是一个对象,参数可以写查询条件,
- all:返回模型类对应表的所有数据,返回值是QuerySet。
- filter:返回满足条件的数据,返回值是QuerySet,参数可以写查询条件。
- exclude:返回不满足条件的数据,返回值是QuerySet,参数可以写查询条件。
- order_by:对查询结果进行排序,返回值是QuerySet,参数中写排序的字段。
- F对象:用于类属性间的比较。
- Q对象:用于条件之间的逻辑关系。
- aggregate:进行聚合操作,返回值是一个字典,进行聚合的时候需要先导入聚合类。
- count:返回结果集中数据的数目,返回值是一个数字。
9. 查询集
all, filter, exclude, order_by调用这些函数会产生一个查询集,QuerySet类对象可以继续调用上面的所有函数。
9.1 查询集特性
- 1) 惰性查询:只有在实际使用查询集中的数据的时候才会发生对数据库的真正查询。
- 2) 缓存:当使用的是同一个查询集时,第一次使用的时候会发生实际数据库的查询,然后把结果缓存起来,之后再使用这个查询集时,使用的是缓存中的结果。
9.2 限制查询集
可以对一个查询集进行取下标或者切片操作来限制查询集的结果。
对一个查询集进行切片操作会产生一个新的查询集,下标不允许为负数。
- 取出查询集第一条数据的两种方式:
- 方式 说明
- b[0] 如果b[0]不存在,会抛出IndexError异常
- b[0:1].get() 如果b[0:1].get()不存在,会抛出DoesNotExist异常。
- 方式 说明
- exists:判断一个查询集中是否有数据。True False