ORM
表------->类
字段----->属性
模型
重点:、
- 模型配置
- 数据的增删改
- 增:book = BookInfo() book.save() 和 BookInfo.objects.create()
- 删:book.delete() 和 BookInfo.objects.get().delete()
- 改:book.name=‘xxx’ book.save() 和 BookInfo.object.get().update(name=xxx)
3.数据的查询 - 基础查询
- F对象和Q对象
- 关联对象
- 查询集QuerySet
一、项目准备
-
创建项目
django-admin startproject bookmanager -
创建应用
python manager.py startapp book -
更换python解释器:按需选择
查看路径:which python -
添加子应用
在INSTALLED_APPS中添加子应用 -
本地化
更改语言,时区
#设置中文
LANGUAGE_CODE = ‘zh-Hans’
#亚洲上海时区
TIME_ZONE = ‘Asia/Shanghai’ -
模板路径
在应用同级目录下,创建templates模板文件夹
在TEMPLATES 中 DIRS 中写入你的templates路径
[os.path.join(BASE_DIR,‘templates’)], -
项目中匹配urls
正则 : 路径只要不是admin/就算匹配成功。并包含到应用中的urls.py
url(r’^’,include(‘book.urls’)) -
应用中匹配urls.py
应用中创建 urls.py
正则 : 路径中包含booklist/,就调用视图中对应的bookList函数
from django.conf.urls import url
from book.views import bookList(
urlpatterns = [
# 匹配书籍列表信息的URL,调用对应的bookList视图
url(r'^booklist/$',bookList)
]
-
准备视图
定义视图:提供书籍列表信息
def bookList(request):return HttpResponse(‘OK!’)
10.开启服务器, 测试项目
进入项目文件中, 开启项目对应的服务器
python manage.py runserver
点击网址查看
二、配置
在settings.py中保存了数据库的连接配置信息,Django默认初始配置使用sqlite数据库
1. 使用MySQL数据库首先需要安装驱动程序
pip install PyMySQL
2. 在Django的 工程 同名子目录的 __init__.py 文件中添加如下语句
import pymysql
pymysql.install_as_MySQLdb()
3. 修改DATABASES配置信息
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': 'mysql', # 数据库用户密码
'NAME': 'book' # 数据库名字
}
}
4. 在MySQL中创建数据库
create database book charset=utf8;
三、定义模型类
模型类被定义在"应用/models.py"文件中。
模型类必须继承自Model类,位于包django.db.models中。
接下来首先以"图书-人物"管理为例进行演示。
1 定义
在models.py 文件中定义模型类。
from django.db import models
# Create your models here.
# 准备书籍列表信息的模型类
class BookInfo(models.Model):
# 创建字段,字段类型...
name = models.CharField(max_length=20, verbose_name='名称')
pub_date = models.DateField(verbose_name='发布日期',null=True)
readcount = models.IntegerField(default=0, verbose_name='阅读量')
commentcount = models.IntegerField(default=0, verbose_name='评论量')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta:
db_table = 'bookinfo' # 指明数据库表名
verbose_name = '图书' # 在admin站点中显示的名称
def __str__(self):
"""定义每个数据对象的显示信息"""
return self.name
# 准备人物列表信息的模型类
class PeopleInfo(models.Model):
GENDER_CHOICES = (
(0, 'male'),
(1, 'female')
)
name = models.CharField(max_length=20, verbose_name='名称')
gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
description = models.CharField(max_length=200, null=True, verbose_name='描述信息')
book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书') # 外键
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta:
db_table = 'peopleinfo'
verbose_name = '人物信息'
def __str__(self):
return self.name
1) 数据库表名
模型类如果未指明表名,Django默认以小写app应用名_小写模型类名为数据库表名。
可通过db_table指明数据库表名。
2) 关于主键
jango会为表创建自动增长的主键列,每个模型只能有一个主键列,
如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。
默认创建的主键列属性为id,可以使用pk代替,pk全拼为primary key。
3) 属性命名限制
不能是python的保留关键字。
不允许使用连续的下划线,这是由django的查询方式决定的。
定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下:
属性=models.字段类型(选项)
Charfiled 必须设置max_length
verbose_name 主要是admin后台显示
4) 外键
在设置外键时,需要通过on_delete选项指明主表删除数据时,
对于外键引用表数据如何处理,在django.db.models中包含了可选常量
-
CASCADE级联,删除主表数据时连通一起删除外键表中数据
-
PROTECT保护,通过抛出ProtectedError异常,来阻止删除主表中被外键应用的数据
-
SET_NULL设置为NULL,仅在该字段null=True允许为null时可用
-
SET_DEFAULT设置为默认值,仅在该字段设置了默认值时可用
-
SET()设置为特定值或者调用特定方法
-
DO_NOTHING不做任何操作,如果数据库前置指明级联性,此选项会抛出IntegrityError异常
2 迁移
将模型类同步到数据库中。
1)生成迁移文件
python manage.py makemigrations
2)同步到数据库中
python manage.py migrate
3 添加数据
在MySQL数据库中添加数据
四、shell工具
shell工具
Django的manage工具提供了shell命令,帮助我们配置好当前工程的运行环境(如连接好数据库等),
以便可以直接在终端中执行测试python语句。
-
通过如下命令进入shell
python manage.py shell -
进入shell后导入你所键的模型类
例:from book.models import BookInfo,PeopleInfo
五、数据库的操作 增、删 、改
1 增加
增加数据有两种方法。
from boook.models import BookInfo
# 方式1
# 需要手动调用 save() -----> book.save()
book = BookInfo(
name='python',
pub_data='2019-06-03'
)
book.save()
# 方式2 直接入库 create -----> 通过模型类.objects.create()保存。
# objects 模型的管理类
# 我们对模型的 增删改查 都找它
BookInfo.objects.create(
name='java',
pub_data='2010-06-06'
)
2 修改
修改更新有两种方法
from boook.models import BookInfo
# 方式1 ( 手动调用save )
# 1.先查询数据
book = BookInfo.objects.get(id=1)
# 2.直接修改实例的属性
book.readcount=20
# 3. 调用save方法
book.save()
# 方式2 直接更新 ( update )
使用模型类.objects.filter().update(),会返回受影响的行数
# filter
BookInfo.objects.filter(id=1).update(
readcount = 100,
commentcount = 200
3 删除
删除有两种方法
# 方式1
# 1. 先查询出数据
book = BookInfo.objects.get(id=5)
# 2. 调用删除方法
book.delete()
# 方式2
模型类.objects.filter().delete()
BookInfo.objects.filter(id=6).delete()
六、数据库的操作—查询
基础条件查询
1 基本查询
1. 查询单一结果,如果不存在会抛出模型类.DoesNotExist异常。
2. all查询多个结果。
3. count查询结果数量。
# 返回一个数据
book = BookInfo.objects.get(id=1)
# 查询的id 不存在时会抛出异常
book = BookInfo.objects.get(id=100)
try:
book = BookInfo.objects.get(id=100)
except BookInfo.DoesNotExist:
pass
# 返回所有结果,是一个列表
BookInfo.objects.all()
# count 返回的是查询到的数量
BookInfo.objects.all().count()
BookInfo.objects.count()
2 过滤查询
实现SQL中的where功能,包括
1. filter过滤出多个结果
2. exclude排除掉符合条件剩下的结果
3. get过滤单一结果
对于过滤条件的使用,上述三个方法相同,故仅以filter进行讲解。
过滤条件的表达语法如下:
属性名称__比较运算符=值
# 属性名称和比较运算符间使用两个下划线,所以属性名不能包括多个下划线
BookInfo-----> 模型类
1)相等
exact:表示判等。
例:查询编号为1的图书。
BookInfo.objects.filter(id__exact=1)
可简写为:
BookInfo.objects.filter(id=1)
--------------------------------------------------------------------------------
# 查询编号为1的图书
# exact 精确的 准确的 就是等于
BookInfo.objects.get(id_exact=1)
BookInfo.objects.get(id=1) # 相当于是第一个的简写
BookInfo.objects.filter(id=1) # 返回的是一个列表 想要获得的是一个对象利用下标的形式
# BookInfo.objects.filter(id=1)[0]
2)模糊查询
contains:是否包含。
说明:如果要包含%无需转义,直接写即可。
例:查询书名包含'传'的图书。
BookInfo.objects.filter(name__contains='传')
startswith、endswith:以指定值开头或结尾。
例:查询书名以'部'结尾的图书
BookInfo.objects.filter(name__endswith='部')
以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,
如iexact、icontains、istartswith、iendswith.
----------------------------------------------------------------------------
# 查询书名包含'湖'的图书
# contains 包含 的意思
BookInfo.objects.filter(name__contains='湖')
# 查询书名以'部'结尾的图书
# endswith 以什么结尾的意思
BookInfo.objects.filter(name__endswith='部')
3) 空查询
isnull:是否为null。
例:查询书名为空的图书。
BookInfo.objects.filter(name__isnull=True)
4) 范围查询
in:是否包含在范围内。
例:查询编号为1或3或5的图书
BookInfo.objects.filter(id__in=[1,3,5])
5)比较查询
gt大于 (greater then)
gte大于等于 (greater then equal)
lt小于 (less then)
lte小于等于 (less then equal)
例:查询编号大于3的图书
BookInfo.objects.filter(id__gt=3)
不等于的运算符,使用exclude()过滤器。
例:查询编号不等于3的图书
BookInfo.objects.filter(id__gt=3)
6)日期查询
year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。
例:查询1980年发表的图书。
BookInfo.objects.filter(pub_date__year=1980)
例:查询1990年1月1日后发表的图书。
BookInfo.objects.filter(pub_date__gt='1990-1-1')
- F和Q对象
F对象 ----> # 对两个属性的比较
语法:
filter (字段名__运算符=F('字段名'))
例:查询阅读量大于等于评论量的图书。
from django.db.models import F
BookInfo.objects.filter(readcount__gt=F('commentcount'))
可以在F对象上使用算数运算。
例:查询阅读量大于2倍评论量的图书。
BookInfo.objects.filter(readcount__gt=F('commentcount')*2)
Q对象
多个过滤器逐个调用表示逻辑与关系,同sql语句中where部分的and关键字。
例:需要查询id 大于2 并且阅读量大于20的书籍
# 方式1
# filter().filter()
BookInfo.objects.filter(id__gt=2).filter(readcount__gt=20)
# 方式2
# filter(条件,条件)
BookInfo.objects.filter(id__gt=2,readcount__gt=20)
如果需要实现逻辑或or的查询,需要使用Q()对象结合|运算符,Q对象被义在django.db.models中。
语法如下:
Q(属性名__运算符=值)
例:需要查询id大于2 或者 阅读量大于40的书籍
from django.db.models import Q
BookInfo.objects.filter(Q(id__gt=2)|Q(readcount__gt=40))
Q对象可以使用&、|连接,&表示逻辑与,|表示逻辑或。
Q对象前可以使用~操作符,表示非not。
例:查询编号不等于3的图书。
BookInfo.objects.filter(~Q(id=3))
- 聚合函数和排序函数
1. 聚合函数
Sum,Max,Min,Avg,Count
聚合函数需要使用 aggregate
语法形式是:aggregate(Xxx('字段'))
# 当前书籍的阅读总量
from django.db.models import Sum,Max,Min,Avg,Count
BookInfo.objects.aggregate(Sum('readcount'))
注意aggregate的返回值是一个字典类型
{'属性名__聚合类小写':值}
如:
{'readcount__sum': 126}
使用count时一般不使用aggregate()过滤器。
例:查询图书总数。
BookInfo.objects.count()
注意count函数的返回值是一个数字。
- 排序
使用order_by对结果进行排序
默认升序
BookInfo.objects.all().order_by('readcount')
降序 在order_by()括号中的参数加上 - 就表示降序
BookInfo.objects.all().order_by('-readcount')
- 关联查询
书籍和人物的关系是 一对多
书籍中没有任何关于人物的字段
人物中有关于书籍的字段 book 外键
语法形式:
通过书籍查询人物信息(已知主表数据,关联查询从表数据)
主模型(实例对象).关联模型类名小写_set.all()
通过人物查询书籍信息(已知 从表数据,关联查询主表数据)
从表模型(实例对象).外键
例: 查询书籍为1的所有人物信息
通过书籍 查询人物
1. 查询书籍
book = BookInfo.objects.get(id=1)
2. 根据书籍关联人物信息
book.perpleinfo_set.all()
例:查询人物为1的书籍信息
根据书籍 查询人物
from boook.models import PerpleInfo
1. 查询人物
person = PerpleInfo.objects.get(id=1)
2. 根据人物关联查询书籍
# person.book 实例对象
person.book
person.book.name # 得到真实的名字
- 关联过滤查询
由多模型类条件查询一模型类数据:
语法如下:
关联模型类名小写__属性名__条件运算符=值
注意:如果没有"__运算符"部分,表示等于。
语法形式
需要的是 书籍信息 ,已知条件是 人物信息
需要的是 主表数据 ,已知条件是 从表信息
filter(关联模型类型小写__字段__运算符=值)
需要的是 人物信息 ,已知条件是 书籍信息
需要的是 从表信息 ,已知条件是 主表信息
filter(外键__字段__运算符=值)
例:查询图书,要求图书人物为"郭靖"
需要的是图书,条件是人物
1. BookInfo.objects.filter(perpleinfo__name__exact='郭靖')
2. BookInfo.objects.filter(perpleinfo__name='郭靖')
例:查询图书,要求图书中人物的描述包含"八"
BookInfo.objects.filter(perpleinfo__description__contains='八')
例:查询书名为“天龙八部”的所有人物
PerpleInfo.objects.filter(book__name='天龙八部')
例:查询图书阅读量大于30的所有人物
PerpleInfo.objects.filter(book__readcount__gt=50)
5.查询集QuerySet
查询集,也称查询结果集、QuerySet,表示从数据库中获取的对象集合。
当调用如下过滤器方法时,Django会返回查询集(而不是简单的列表):
1. all():返回所有数据。
2. filter():返回满足条件的数据。
3. exclude():返回满足条件之外的数据。
4. order_by():对结果进行排序。
2 两大特性
1)惰性执行
创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用
例如,当执行如下语句时,并未进行数据库查询,只是创建了一个查询集books
books = BookInfo.objects.all()
继续执行遍历迭代操作后,才真正的进行了数据库的查询
for book in books:
print(book.name)
2)缓存
使用同一个查询集,第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,
再次使用这个查询集时会使用缓存的数据,减少了数据库的查询次数。
情况一:如下是两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载。
from book.models import BookInfo
[book.id for book in BookInfo.objects.all()]
[book.id for book in BookInfo.objects.all()]
情况二:经过存储后,可以重用查询集,第二次使用缓存中的数据。
books=BookInfo.objects.all()
[book.id for book in books]
[book.id for book in books]
3 限制查询集
可以对查询集进行取下标或切片操作,等同于sql中的limit和offset子句。
注意:不支持负数索引。
对查询集进行切片后返回一个新的查询集,不会立即执行查询。
如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,
[0:1].get()如果没有数据引发DoesNotExist异常。
示例:获取第1、2项,运行查看。
books = BookInfo.objects.all()[0:2]
books
- 分页
#查询数据
books = BookInfo.objects.all()
#导入分页类
from django.core.paginator import Paginator
#创建分页实例
paginator=Paginator(books,2)
#获取指定页码的数据
page_skus = paginator.page(1)
#获取分页数据
total_page=paginator.num_pages