Django模型层(各种表及表数据的操作)
一、Django模型层
0. django模型层的级联关系
- django 1.x版本默认有级联关系
- django 2.x版本的级联关系需要自己配置
1. 配置django测试脚本
- 共有两种配置方式
(1)方式一
- 直接字某一个应用文件夹下的test文件中写下面的内容
- 取manage.py文件中拷贝其前四行代码
- 再自己写两行代码
- 在下面直接写测试的代码即可
# manage.py中拷贝的前四行
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")
# 自己写的两行
import django
django.setup()
# 一定要等待测试脚本搭建完毕之后 才能导入django文件进行测试
from app01 import models
(2)方式二
- 直接新建一个任意名称的py文件配置方式一的内容。
2. orm表数据的两种增删改
(1)方式一:
- 利用queryset对象的方法
- filter方法查询出来的结果是一个Queryset对象
1. 创建表记录
book_obj = models.Books.objects.create(title='三国演义',price=123.23,publish_date='2019-11-11')
print(book_obj)
2. 修改表记录
models.Books.objects.filter(pk=1).update('title'='aaa')
3. 删除数据
models.Books.objects.filter(pk=3).delete()
(2)方式二:
- 利用数据对象本身的方法
1. 创建表记录
book_obj = models.Books(title='西游记',price=666.66,publish_date='2000-1-21')
book_obj.save()
2. 修改表数据
book_obj = models.Books.objects.get(pk=1)
book_obj.price = 222.66
book_obj.save() # 该方法不推荐使用,因为他会把该行所有字段数据全都用新的数据覆盖一遍,造成资源的浪费,且效率也降低了。 推荐使用queryset方法
3. 删除表数据
book_obj = models.Books.objects.get(pk=3)
book_obj.delete()
3. pk关键字和queryset对象特点,orm中打印SQL语句
(1)pk关键字
# pk关键字的作用:
1. pk会自动帮你查找到当前表的主键字段,所以后期我们都是用pk来指代主键字段
user_obj_list = models.Books.objects.filter(pk=1)
(2)queryset对象的特点
# queryset对象的特点:
1.只要是queryset对象就可以无限制的调用queryset的方法
如:res = models.Books.objects.filter(pk=1).filter().filter().filter().filter()
2.只要是queryset对象就可以点query查看当前结果内部对应的sql语句
如:
res.query
结果:SELECT `app01_books`.`id`, `app01_books`.`title`, `app01_books`.`price`, `app01_books`.`publish_date` FROM `app01_books` WHERE `app01_books`.`id` = 1
(3)orm中对数据库操作时打印SQL语句
实现方法:
在django项目的settings文件中,添加LOGGING配置即可。
即:将下面的代码直接拷贝到settings文件中
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
4. orm表单操作必会13条
(1)all()
查所有
- 返回的结果QuerySet对象
- 没有参数
- orm语句的查询默认都是惰性查询,只有当你真正要使用数据的时候才会执行orm语句。类似生成器。
(2)filter()
筛选
- 返回的结果QuerySet对象,支持多个关键字参数,并且是and关系
- 根据查询条件得到数据对象可以是多个
- 结果不存在返回空
(3)get()
筛选,不推荐使用
- 获取的是数据对象本身
- 根据查询条件得到数据对象必须是唯一的
- 结果不存在直接报错
(4) first()
- 取queryset对象中第一个数据对象
(5)last()
- 取queryset对象中最后一个数据对象
(6)count()
统计数据对象的个数
结果是一个数字类型
num = models.Books.objects.count()
(7)values()
获取数据对象中指定的字段的值
可以有多个参数
得到的是queryset对象,列表套字典的格式
res = models.Books.objects.values('title','price')
print(res) # <QuerySet [{'title': '三国演义', 'price': Decimal('222.66')}, {'title': '红楼梦', 'price': Decimal('888.99')}]>
(8)values_list()
获取数据对象中指定的字段的值
可以有多个参数
得到的是queryset对象,列表套元组的格式
res = models.Books.objects.values_list('title','price')
print(res) # <QuerySet [('三国演义', Decimal('222.66')), ('红楼梦', Decimal('888.99')), ('西游记', Decimal('444.66')), ('西游记', Decimal('666.22'))]>
(9)order_by()
排序
按照指定的字段排序
默认是升序
降序 字段前面加负号
res = models.Books.objects.order_by('price')
res1 = models.Books.objects.all().order_by('-price')
(10)reverse()
颠倒顺序
前提是颠倒的对象必须有顺序(提前排序之后才能跌倒)
res1 = models.Books.objects.all().reverse() # 没有作用
res2 = models.Books.objects.all().order_by('price')
res3 = models.Books.objects.all().order_by('price').reverse()
(11)exclude()
排除什么什么之外
得到的是queryset对象
查询除了title为三国演义以外的其他所有数据对象
res = models.Books.objects.all().exclude(title='三国演义')
print(res) # <QuerySet [<Books: 红楼梦>, <Books: 西游记1>, <Books: 西游记2>]>
(12)exists()
判断查询结果是否有值,返回结果是一个布尔值
该方法其实不需要使用,因为数据本身自带布尔值
res = models.Books.objects.filter(pk=1).exists()
print(res)
# True
(13)distinct()
去重
对查询结果进行去重操作
去重的前提:数据必须是完全相同的情况下才能够去重,包括主键也要相同(你容易忽略主键)
res1 = models.Books.objects.values('title','price')
res2 = models.Books.objects.values('title','price').distinct()
print(res1, res2)
5. 双下划线查询
- 即有比较运算符的查询
询价格大于500的书籍
res = models.Books.objects.filter(price__gt=500)
print(res)
查询价格小于400 的书籍
res = models.Books.objects.filter(price__lt=400)
print(res)
查询价格大于等于500
res = models.Books.objects.filter(price__gte=444.66) python对数字精确度不敏感
res = models.Books.objects.filter(price__gte=500)
print(res)
查询价格小于等于500的书籍
res = models.Books.objects.filter(price__lte=500)
print(res)
查询价格是222.66或者444.22或者500的书籍
res = models.Books.objects.filter(price__in=[222,444,500])
print(res)
查询价格在200到800之间的书籍
res = models.Books.objects.filter(price__range=(200,800)) # __range 顾头顾尾
print(res)
查询出版日期是2019年的书籍
res = models.Books.objects.filter(publish_date__year='2019')
print(res)
查询出版日期是1月份的书籍
res = models.Books.objects.filter(publish_date__month='1')
print(res)
6. 模糊查询
MySQL中的模糊查询
关键字 like
模糊匹配的符号
%:匹配任何个数的任意字符
_:匹配一位任意的字符
模糊查询实例演示:
查询书籍是以三开头的书
res = models.Books.objects.filter(title__startswith='三')
print(res)
查询书籍是以义结尾的书
res = models.Books.objects.filter(title__endswith='1')
print(res)
查询书籍名称中包含游字的书籍
res = models.Books.objects.filter(title__contains='游')
print(res)
查询书籍名称中包含字母p的书籍
res = models.Books.objects.filter(title__contains='p') # 默认区分大小写
res = models.Books.objects.filter(title__icontains='p') # 忽略大小写 加i
print(res)
7. 两表表数据的增删改
(1)以下一对多,多对多使用的模型类如下:
- 图书表和出版社表是一对多的关系,图书表和作者表是多对多的关系,作者和作者详情是一对一的关系。
from django.db import models
# Create your models here.
class Books(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish_date = models.DateField()
def __str__(self):
return self.title
# 表查询 以图书管理系统为例
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish_date = models.DateField(auto_now_add=True)
"""
auto_now:每次修改的数据的时候 都会自动更新修改书籍(展示最新的一次修改时间)
auto_now_add:当数据创建出来的时候 会自动将创建时间记录下来
"""
publish = models.ForeignKey(to='Publish')
authors = models.ManyToManyField(to='Author')
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64)
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=32)
email = models.EmailField() # 对应到数据库中仅仅是varchar(254) 没有任何的限制条件 该字段只要是字符串就可以
# 仅仅是为了表达语义 如何限制 后期需要借助于校验性组件
author_detail = models.OneToOneField(to='AuthorDetail')
def __str__(self):
return self.name
class AuthorDetail(models.Model):
phone = models.BigIntegerField()
addr = models.CharField(max_length=64)
def __str__(self):
return self.addr
(2)对象点外键字段
# 点外键字段
一对多中:
print(book_obj.publish) # 获取到外键关联的数据对象
多对多中:
print(book_obj.authors) # 已经跨到第三张表了
1. 一对多
(1)增
- 向图书表中添加一条记录
# 第一种直接放具体的值
models.Book.objects.create(title='三国演义',price=222.33,publish_id=1) # 直接传表里面的实际字段,即 publish_id=1
# 第二种放数据对象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='红楼梦',price=444.33,publish=publish_obj) # 传虚拟字段,即 publish=publish_obj
(2)改
- 把图书表中主键为1的图书出版社改为publish_id=2对应的出版社
# 第一种直接放具体的值
models.Book.objects.filter(pk=1).update(publish_id=2)
# 第二种放数据对象
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)
(3)删
- 删除出版社表中主键为1的出版社
models.Publish.objects.filter(pk=1).delete() # 默认就是级联删除 级联更新
2. 多对多表数据的增删改
(1)增
- 用
add()
方法
add方法 能够朝第三张关系表添加数据
既支持传数字
add(1,2)
也支持传对象
add(author_obj,author_obj1)
并且两者都可以是多个
- 实例:
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.authors) # 已经跨到第三张表了
# 第一种:直接放具体的值
book_obj.authors.add(1) # 在第三张表里面给主键为2书籍绑定一个主键为1的作者
book_obj.authors.add(1,2) # 在第三张表里面给主键为2书籍绑定一个主键为1和2的作者
# 第二种:放数据对象
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.add(author_obj) # 在第三张表里面给主键为2书籍绑定一个主键为1的作者
book_obj.authors.add(author_obj,author_obj1) # 在第三张表里面给主键为2书籍绑定一个主键为1和2的作者
(2)改
- 用
set()
方法
set修改多对多关系表中的数据
set修改数据的原理是先把原来的正行数据删除,再新增一行修改后的数据
既可以传数字也可以传对象
但是需要注意的是括号内必须是可迭代对象*****************
都支持多个
set((1,3))
set((author_obj,author_obj1))
- 实例:
book_obj = models.Book.objects.filter(pk=2).first()
# 第一种:
book_obj.authors.set((1,3)) # 将主键为2的图书的作者改为主键为1和3的作者
book_obj.authors.set([1,]) # 将主键为2的图书的作者改为主键为1的作者
# 第二种:
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.set((author_obj,author_obj1))
(3)删
- 用
remove()
方法
remove既可以传数字 也可以穿对象
并且都支持传多个 不需要迭代
remove(1,2)
remove(author_obj,author_obj1)
- 实例:
book_obj = models.Book.objects.filter(pk=2).first()
# 第一种:
book_obj.authors.remove(100) # 将主键为2的图书的作主键为100的作者,没有这个作者主键,就不操作。
book_obj.authors.remove(1,2) # 将主键为2的图书的主键为1和2的作者删除
# 第二种:
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.remove(author_obj)
book_obj.authors.remove(author_obj,author_obj1)
(4)清空
使用
clear()
方法删除某个数据在第三张表中的所有记录
clear清空书籍相关所有记录 括号内不需要传递参数
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.clear() # 删除主键为2的图书在第三张表中的所有记录
8. 跨表查询
- 两种查询方式:
- 通过对象查询,运用子查询原理
- 通过双下划线,运用联表原理
(1)正反向查询
正反向查询
关系字段即外键字段在表1中 由表1查表2的内容就是正向
否则 就是反向
正向查询按字段
反向查询按表名小写 + _set
"""
什么时候需要加all()
当正向查询点击外键字段数据有多个的情况下 需要.all()
app01.Author.None 一旦看到该结果 只需要加.all()即可
在写orm语句的时候跟你写sql语句一样 不要想着一次性写完
写一点查一点再写一点
"""
"""
什么时候反向查询的时候表名小写需要加_set
一对多
多对多
一对一不需要加_set
"""
1. 通过对象查询,即子查询方式
(1)原理
- 子查询(就是分步操作的来查询)
(2)两表子查询实例:
# 正向查询:**********************
1.查询书籍主键为2的出版社名称
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.publish) # 出版社对象
print(book_obj.publish.name)
2.查询书籍主键为4的作者姓名
book_obj = models.Book.objects.filter(pk=4).first()
print(book_obj.authors) # app01.Author.None
print(book_obj.authors.all())
3.查询作者是jason的手机号码
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.author_detail)
print(author_obj.author_detail.phone)
"""
什么时候需要加all()
当正向查询点击外键字段数据有多个的情况下 需要.all()
app01.Author.None 一旦看到该结果 只需要加.all()即可
在写orm语句的时候跟你写sql语句一样 不要想着一次性写完
写一点查一点再写一点
"""
# 反向查询:**********************
4.查询出版社是东方出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
# print(publish_obj.book_set) # app01.Book.None
print(publish_obj.book_set.all())
5.查询作者是jason写过的书籍
author_obj = models.Author.objects.filter(name='jason').first()
# print(author_obj.book_set) # app01.Book.None
print(author_obj.book_set.all()) # app01.Book.None
6.查询手机号是120的作者姓名
author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first()
print(author_detail_obj.author)
print(author_detail_obj.author.email)
2. 双下划线式联表查询
(1)原理
"""
inner join
left join
right join
union
"""
记住这个原理:**********利用左连接和右连接等原理,把几张表组成一张大表,再在大表中进行查询********
正向 :models.Book.objects.filter(pk=2).values('publish__name')
values(类中的外键字段) 表示跨到publish这张表,再加上 __字段名 , 表示取该表的该字段的值。
通过values(类的外键字段1__类的外键字段2__类的外键字段3__表3中的字段名) 可以实现无限跨表。
反向 :models.Publish.objects.filter(book__pk=2) ,表名小写__字段名 ,表示把该表的该字段当做查询条件,因为有表名小写__字段名,此时相当于把publish表和book表给连接起来组成一张大表了。
(2)两表联查实例:
# 正向查询:***************************
1.查询书籍pk为2的出版社名称
正向
res = models.Book.objects.filter(pk=2).values('publish__name') # 写外键字段就相当于已经跨到外键字段所关联的表
你想要改表的哪个字段信息 你只需要加__获取即可
print(res)
反向
res = models.Publish.objects.filter(book__pk=2).values('name')
print(res)
2.查询书籍pk为2的作者姓名和邮箱
res = models.Book.objects.filter(pk=2).values('authors__name','authors__email')
print(res)
res = models.Author.objects.filter(book__pk=2).values('name','email')
print(res)
# 反向查询:*****************************
3.查询作者是egon的家庭地址
res = models.Author.objects.filter(name='egon').values('author_detail__addr')
print(res)
res = models.AuthorDetail.objects.filter(author__name='egon').values('addr')
print(res)
4.查询出版社是东方出版社出版过的书的名字
res = models.Publish.objects.filter(name='东方出版社').values('book__title')
print(res)
res = models.Book.objects.filter(publish__name='东方出版社').values('title')
print(res)
3. 三表及以上联表查询实例:
- 通过外键关系,以顺藤摸瓜式的思想,从一张表到其他表。
查询书籍pk是2的作者的手机号
res = models.Book.objects.filter(pk=2).values('authors__author_detail__phone')
print(res)
res = models.Author.objects.filter(book__pk=2).values('author_detail__phone')
print(res)
Django模型层(各种表及表数据的操作)的更多相关文章
- {django模型层(二)多表操作}一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询、分组查询、F查询和Q查询
Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 xxx 七 ...
- Django模型层之单表操作
Django模型层之单表操作 一 .ORM简介 我们在使用Django框架开发web应用的过程中,不可避免地会涉及到数据的管理操作(如增.删.改.查),而一旦谈到数据的管理操作,就需要用到数据库管理软 ...
- Django模型层:单表操作,多表操作,常用(非常用)字段和参数,Django-model进阶
一.web应用 二.模板的导入与继承 三.静态文件相关 四.inclusion_tag:返回html片段 五.模型层 一.web应用 -s包括两个部分:web服务器+application -目前阶段 ...
- day 70 Django基础五之django模型层(二)多表操作
Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 ORM ...
- day 69 Django基础五之django模型层(一)单表操作
Django基础五之django模型层(一)单表操作 本节目录 一 ORM简介 二 单表操作 三 章节作业 四 xxx 一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现 ...
- day 56 Django基础五之django模型层(二)多表操作
Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 ORM ...
- day 55 Django基础五之django模型层(一)单表操作
Django基础五之django模型层(一)单表操作 本节目录 一 ORM简介 二 单表操作 三 章节作业 四 xxx 一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它 ...
- Django 08 Django模型基础3(关系表的数据操作、表关联对象的访问、多表查询、聚合、分组、F、Q查询)
Django 08 Django模型基础3(关系表的数据操作.表关联对象的访问.多表查询.聚合.分组.F.Q查询) 一.关系表的数据操作 #为了能方便学习,我们进入项目的idle中去执行我们的操作,通 ...
- django 模型层(2)
Django 模型层(2) 多表操作---模型之间的关系 1 一对一:作者----作者详细信息 2 一对多:书籍----出版社 3 多对多:书籍----作者 一 创建模型(主键(id)自动创建) 没 ...
随机推荐
- PC端网页嵌入百度地图
1 打开百度地图生成器: http://api.map.baidu.com/lbsapi/creatmap/ 2 设置好了之后,点击获取代码,将代码粘贴到文件中保存为html文件 参考网址:https ...
- 使用canvas实现对图片的批量打码
最近有个需求,利用h5的canvas对图片一些涉及个人隐私的地方进行打码再上传,而且最好能实现批量打码.意思是在一张图片上对哪些地方做了打码,后续的所有图片都在同样的地方也可以自动打上码,不用人工一张 ...
- java课堂疑问解答与思考2
问题一 编写一个方法,使用以上算法生成指定数目(比如1000个)的随机整数. 答:Xn+1=(7^5*Xn)mod(2^31-1) 程序源码: import java.util.Random; imp ...
- 企业应用学习-git学习
1.git的基本使用 git与svn的区别 GIT 是分布式的,SVN 不是:这是 GIT 和其它非分布式的版本控制系统,例如 SVN,CVS 等,最核心的区别. GIT 把内容按元数据方式存储,而 ...
- [ASP.NET] 解决点击控件下载文件没有响应的问题
下载文件的方法是使用http响应输出流来实现的,使用到了response.write() 导致下载文件时点击控件出错,没有响应,也获取不了文件 是因为在母版页使用了updatepanel,因此回传时发 ...
- Django框架中使用Echart进行统计的SQL语句
最近想用Echart做数据统计的图形显示,数据来源是MySQL数据库,自然需要根据不同的搜索条件筛选出表中的数据,用比较多的就是时间的参数吧! 常用的mysql时间的条件进行检索的SQL语句: 数据表 ...
- Oracle 单实例安装篇
linux中启动网卡报错:Error: Connection activation failed: Connection 'eth0' is not available on the device e ...
- C语言--浮点数
在程序中使用浮点数 -- 浮点数的精确性有限 -- 在从c语言中float类型的精确度只到小数点的7位 -- 浮点数只能在一定范围内去相信它 -- 在有精确度高的要求下不要使用浮点数(在算钱的时候,误 ...
- CF 1136C Nastya Is Transposing Matrices
题目链接:http://codeforces.com/problemset/problem/1136/C 题目分析 看了题目之后,第一想法:任意位置都可以倒置,要是枚举,铁定的超时.所以需要探索规律. ...
- html之input
<input>在w3c中解释的是用于搜集用户的信息 它其实就是一个输入框,根据type的不同这个框可以用作不同的功能可以输入一个文本,可以定义一个按钮什么的. 属性type一些值的介绍 1 ...