Django MTV之model
Django ORM
O(objects):类和对象。
R(Relation):关系,关系数据库中的表格。
M(Mapping):映射。
Django ORM框架的功能:
a) 建立模型类和表之间的对应关系,允许我们通过面向对象的方式来操作数据库。
b) 根据设计的模型类生成数据库中的表格。
c) 通过方便的配置就可以进行数据库的切换。
1. Django数据库配置
2.1 mysql命令回顾
登录mysql数据库:mysql –uroot –p
查看有哪些数据库:show databases
创建数据库:create database test charset=utf8; #切记:指定编码
使用数据库:use test;
查看数据库中的表:show tables;
2.2 Django配置使用mysql数据库
修改settings.py中的DATABASES。
注意:django框架不会自动帮我们生成mysql数据库,所以我们需要自己去创建(也就是说只能生成表)。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'test', 'USER': 'root', 'PASSWORD':'ROOT', 'HOST':'', # 空代表连接本机 'PORT': 3306 , } }
2.3 切换mysql数据库之后不能启动服务器
需要安装操作mysql数据库的包,python2环境和python3环境有以下区别。
a) python2需要安装mysql-python:
pip install mysql-python
b) python3需要安装pymysql:
pip install pymysql
python3中安装好pymysql,需要在test/__init__.py中加如下内容:
import pymysql pymysql.install_as_MySQLdb()
2.模型类设计
2.1 在应用models.py中设计模型类。
必须继承与models.Model类。
1) 设计Book类。
2) 设计Hero类。
Models.ForeignKey可以建立两个模型类之间一对多的关系,django在生成表的时候,就会在多端的表中创建一列作为外键,建立两个表之间一对多的关系。
#models.py from django.db import models # models.字段类型(约束条件) class Book(models.Model): # 一类 btitle = models.CharField(max_length=10,) bpub_date = models.DateField(default='1990-01-01') class Hero(models.Model): # 多类 hname = models.CharField(max_length=10,) hgender = models.BooleanField(default=False) hskill = models.CharField(max_length=10,) hbook = models.ForeignKey('Book',on_delete=models.CASCADE) # 注意:1.'Book'也可以不加引号,但需要注意,不加引号意思是从变量Book去找对应的多类, # 所以Book类要写在Hero类前面,预加载时才可以正确读取到此变量。 # 2.Django 2.0版本以后,在定义ForeignKey 的时候, # 必须给on_delete字段给值,CASCADE为级联删除,DO_NOTHING是 什么也不干。
2.2 模型类生成表
1) 生成迁移文件
命令:python manage.py makemigrations
迁移文件是根据模型类生成的。
2) 执行迁移生成表
命令:python mange.py migrate
根据迁移文件生成表。
生成表名的默认格式为: 应用名_模型类名小写 ( 此例应用为books )
3 通过模型类操作数据表
首先导入模型类:
from book.models import Book,Hero
1) 向books_book表中插入一条数据。
方式一:通过定义一个对象,对对象进行操作。
b = Book() #定义一个BookInfo类的对象 b.btitle ='天龙八部' #定义b对象的属性并赋值 b.bpub_date = '1990-1-1' b.save() #才会将数据保存进数据库
方式二:通过 对象.objects.create(字段1=值1,字段2=值2) 插入一条数据
Book.objects.create(btitle='水浒传',bpub_date='1990-1-1') #
2) 查询出books_book表中id为1的数据。
b = Book.objects.get(id=1)
3) 在上一步的基础上改变b对应图书的出版日期。
b.bpub_date = ‘1989,10,21’
b.save() #才会更新表格中的数据
或者b.update(‘1989,10,21’) 此法不用save
4) 紧接上一步,删除b对应的图书的数据。
b.delete() #才会删除
5) 向books_hero表中插入一条数据。
h = Hero()
h.hname = '郭靖'
h.hgender = False
h.hcomment = ‘降龙十八掌’
b2 = Book.objects.get(id=2)
h.hbook = b2 #给关系属性赋值,英雄对象所属的图书对象
h.save()
或者 通过create方法直接创建
Book.objects.create(hname = '郭靖',hgender = False,hgender = False)
Book.objects.create(**kwargs)如果参数很多,可以直接**解包传入
6) 查询图书表里面的所有内容。
BookInfo.objects.all()
HeroInfo.objects.all()
通过模型类.objects属性可以调用如下函数,实现对模型类对应的数据表的查询。
以下函数中,只有get的返回值是一个模型类对象,其他的返回值均为QuerySet类型,
函数名 |
功能 |
返回值 |
说明 |
get |
返回表中满足条件的一条且只能有一条数据。 |
返回值是一个模型类对象。 |
参数中写查询条件。 1) 如果查到多条数据,则抛异常MultipleObjectsReturned。 2)查询不到数据,则抛异常:DoesNotExist。 |
all |
返回模型类对应表格中的所有数据。 |
返回值是QuerySet类型 |
查询集 |
filter |
返回满足条件的数据。 |
返回值是QuerySet类型 |
参数写查询条件。 |
exclude |
返回不满足条件的数据。 |
返回值是QuerySet类型 |
参数写查询条件。 |
order_by |
对查询结果进行排序。 |
返回值是QuerySet类型 |
参数中写根据哪些字段进行排序。 |
3.1 关联操作
关联操作:当有多个model且多个model间有关联(多张表有关联)时,我们需要用到关联查询,取到我们所需要的数据。
数据准备:
books_hero
books_book
此时,多个hero对应一本书book,两张表存在多对一的关系,此种情况,我们统一叫一对多。
3.2关联查询(一对多)
在一对多关系中,一对应的类我们把它叫做一类,多对应的那个类我们把它叫做多类,我们把多类中定义的建立关联的类属性叫做关联属性。
例:查询id为1的图书关联的英雄的信息。
b=Book.objects.get(id=1)
b.hero_set.all()
1)通过模型类查询:
Hero.objects.filter(hbook__id=1)
例:查询id为1的英雄关联的图书信息。
h = Hero.objects.get(id=1)
h.hbook
Book.objects.filter(hero__id=1)
格式:
由一类的对象查询多类的时候: hero_obj = Book.objects.get(id=1).hero_set.all()
一类的对象.多类名小写_set.all() #查询所有所对应的多类数据
由多类的对象查询一类的时候: book_obj = Hero.objects.get(id=1).hbook
多类的对象.关联属性 #查询多类的对象对应的一类的对象
通过双下划线实现由多类的对象查询一类对象的时候: Hero.objects.filter(hbook_id=1)
多类的对象. objects.filter(关联属性_id=值)
2)通过模型类实现关联查询
例:查询图书信息,要求图书关联的英雄的技能包含'天'。
Book.objects.filter(hero__hskill__contains='天')
例:查询图书信息,要求图书中的英雄的id大于3.
Book.objects.filter(hero__id__gt=3)
例:查询书名为“天龙八部”的所有英雄。
Hero.objects.filter(hbook__btitle='天龙八部')
通过多类的条件查询一类的数据:
一类名.objects.filter(多类名小写__多类属性名__条件名)
通过一类的条件查询多类的数据:
多类名.objects.filter(关联属性__一类属性名__条件名)
条件名:
__lt 小于 __gt 大于 __contains 包含
注:为帮助理解记忆,此出的第一个双下划线可以简单的理解为 对象.属性 中的 .
3).插入、更新和删除
调用一个模型类对象的save方法的时候就可以实现对模型类对应数据表的插入和更新。
调用一个模型类对象的delete方法的时候就可以实现对模型类对应数据表的数据删除。
4)QuerySet的values和values_list
在通过模型类对象查询之后所得到的查询集QuerySet
例如:查找天龙八部所对应的英雄
queryset = Hero.objects.filter(hbook__btitle='天龙八部') print(queryset.values()) #values(*field) values的参数可以填写你所需要的字段 输出: <QuerySet [{'id': 1, 'hname': '虚竹', 'hgender': True, 'hskill': '天山折梅手', 'hbook_id': 1}, {'id': 2, 'hname': '段誉', 'hgender': True, 'hskill': '凌波微步', 'hbook_id': 1}, {'id': 3, 'hname': '乔峰', 'hgender': True, 'hskill': '降龙十八掌 ', 'hbook_id': 1}]> # queryset.values 输出是包含一个字典集合 print(book_obj.values_list()) 输出:<QuerySet [(1, '虚竹', True, '天山折梅手', 1), (2, '段誉', True, '凌波微步', 1), (3, '乔峰', True, '降龙十八掌', 1)]> # queryset.values_list() 输出是包含一个元组集合
3.3关联查询(多对多)
# models.py from django.db import models class Book(models.Model): btitle = models.CharField(max_length=10,) bpub_date = models.DateTimeField(default='1990-01-01') authors = models.ManyToManyField('Author') # 多对多字段,定义在Author类中也可以 def __str__(self): return self.btitle class Author(models.Model): name = models.CharField(max_length=10)
例子中,一本书可以是多个作者写,多个作者也可以写一本书,所以其对应关系是多对多。
在定义字段是用ManyToManyField定义,
其在生成对应表(book表,author表,book_authors表)的时候会生成表名为: book_authors
也就是: 定义多对多的类名小写__多对多字段名
1)向book_authors表中添加数据(add方法):
book_obj = Book.objects.get(id=1) # 拿到id=1的书对象
author_obj = author.objects.all() #拿到需要添加的作者对象
book_obj .authors.add(*author_obj ) #将作者对象添加到book_author表中,注意*是将author_obj 集合解包,如果其是get拿到的只有一个对象,就不用加*
2)从book_authors表中删除数据(remove方法):
book_obj = Book.objects.get(id=1) # 拿到id=1的书对象
book_obj .authors.remove(1) #将作者id=1的对象从book_obj .authors中移除
4 查询函数
a)空查询 isnull
例:查询书名不为空的图书。isnull
select * from books_book where btitle is not null;
Book.objects.filter(btitle__isnull=False)
b)范围查询 in
例:查询id为1或3或5的图书。
select * from books_book where id in (1,3,5);
Book.objects.filter(id__in = [1,3,5])
c)比较查询 gt(greate than) lt(less than) gte(equal) 大于等于 lte 小于等于
例:查询id大于3的图书。
Select * from books_book where id>3;
Book.objects.filter(id__gt=3)
d)日期查询
例:查询1980年发表的图书。
Book.objects.filter(bpub_date__year=1980)
例:查询1980年1月1日后发表的图书。
from datetime import date
Book.objects.filter(bpub_date__gt=date(1980,1,1))
e)exclude方法:
例:查询id不为3的图书信息。
Book.objects.exclude(id=3)
f)order_by方法:
作用:进行查询结果进行排序。
例:查询所有图书的信息,按照id从小到大进行排序。
Book.objects.all().order_by('id')
例:查询所有图书的信息,按照id从大到小进行排序。
Book.objects.all().order_by('-id')
1. F对象
作用:用于类属性之间的比较。
使用之前需要先导入:
from django.db.models import F
例:查询图书阅读量大于评论量图书信息。
BookInfo.objects.filter(bread__gt=F('bcomment'))
例:查询图书阅读量大于2倍评论量图书信息。
BookInfo.objects.filter(bread__gt=F('bcomment')*2)
2. 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))
3. 聚合函数
作用:对查询结果进行聚合操作。
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.aggregate(Sum('bread'))
{'bread__sum': 126}
count函数 返回值是一个数字
作用:统计满足条件数据的数目。
例:统计所有图书的数目。
BookInfo.objects.all().count()
BookInfo.objects.count()
例:统计id大于3的所有图书的数目。
BookInfo.objects.filter(id__gt=3).count()
小结:
5. 查询集
all, filter, exclude, order_by调用这些函数会产生一个查询集,QuerySet类对象可以继续调用上面的所有函数。
5.1 查询集特性
1) 惰性查询:只有在实际使用查询集中的数据的时候才会发生对数据库的真正查询。
2) 缓存:当使用的是同一个查询集时,第一次使用的时候会发生实际数据库的查询,然后把结果缓存起来,之后再使用这个查询集时,使用的是缓存中的结果。
5.2 限制查询集
可以对一个查询集进行取下标或者切片操作来限制查询集的结果。
对一个查询集进行切片操作会产生一个新的查询集,下标不允许为负数。
取出查询集第一条数据的两种方式:
方式 |
说明 |
b[0] |
如果b[0]不存在,会抛出IndexError异常 |
b[0:1].get() |
如果b[0:1].get()不存在,会抛出DoesNotExist异常。 |
exists() 方法:判断一个查询集中是否有数据。True False
5.3 QuerySet 查询集特点:
1.可迭代
2.可切片