Django模型层(各种表及表数据的操作)

1|0一、Django模型层

1|10. django模型层的级联关系

  • django 1.x版本默认有级联关系
  • django 2.x版本的级联关系需要自己配置

1|21. 配置django测试脚本

  • 共有两种配置方式

1|0(1)方式一

  • 直接字某一个应用文件夹下的test文件中写下面的内容
  1. 取manage.py文件中拷贝其前四行代码
  2. 再自己写两行代码
  3. 在下面直接写测试的代码即可
# 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

1|0(2)方式二

  • 直接新建一个任意名称的py文件配置方式一的内容。

1|32. orm表数据的两种增删改

1|0(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()

1|0(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()

1|43. pk关键字和queryset对象特点,orm中打印SQL语句

1|0(1)pk关键字

# pk关键字的作用: 1. pk会自动帮你查找到当前表的主键字段,所以后期我们都是用pk来指代主键字段 user_obj_list = models.Books.objects.filter(pk=1)

1|0(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

1|0(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', }, } }

1|54. orm表单操作必会13条

1|0(1)all()查所有

  • 返回的结果QuerySet对象
  • 没有参数
  • orm语句的查询默认都是惰性查询,只有当你真正要使用数据的时候才会执行orm语句。类似生成器。

1|0(2)filter() 筛选

  • 返回的结果QuerySet对象,支持多个关键字参数,并且是and关系
  • 根据查询条件得到数据对象可以是多个
  • 结果不存在返回空

1|0(3)get() 筛选,不推荐使用

  • 获取的是数据对象本身
  • 根据查询条件得到数据对象必须是唯一的
  • 结果不存在直接报错

1|0(4) first()

  • 取queryset对象中第一个数据对象

1|0(5)last()

  • 取queryset对象中最后一个数据对象

1|0(6)count()

  • 统计数据对象的个数

  • 结果是一个数字类型

  • num = models.Books.objects.count()

1|0(7)values()

  • 获取数据对象中指定的字段的值

  • 可以有多个参数

  • 得到的是queryset对象,列表套字典的格式

  • res = models.Books.objects.values('title','price') print(res) # <QuerySet [{'title': '三国演义', 'price': Decimal('222.66')}, {'title': '红楼梦', 'price': Decimal('888.99')}]>

1|0(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'))]>

1|0(9)order_by() 排序

  • 按照指定的字段排序

  • 默认是升序

  • 降序 字段前面加负号

  • res = models.Books.objects.order_by('price') res1 = models.Books.objects.all().order_by('-price')

1|0(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()

1|0(11)exclude()

  • 排除什么什么之外

  • 得到的是queryset对象

  • 查询除了title为三国演义以外的其他所有数据对象 res = models.Books.objects.all().exclude(title='三国演义') print(res) # <QuerySet [<Books: 红楼梦>, <Books: 西游记1>, <Books: 西游记2>]>

1|0(12)exists()

  • 判断查询结果是否有值,返回结果是一个布尔值

  • 该方法其实不需要使用,因为数据本身自带布尔值

  • res = models.Books.objects.filter(pk=1).exists() print(res) # True

1|0(13)distinct() 去重

  • 对查询结果进行去重操作

  • 去重的前提:数据必须是完全相同的情况下才能够去重,包括主键也要相同(你容易忽略主键

  • res1 = models.Books.objects.values('title','price') res2 = models.Books.objects.values('title','price').distinct() print(res1, res2)

1|65. 双下划线查询

  • 即有比较运算符的查询
询价格大于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) 查询价格在200800之间的书籍 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)

1|76. 模糊查询

  • 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)

1|87. 两表表数据的增删改

1|0(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

1|0(2)对象点外键字段

# 点外键字段 一对多中: print(book_obj.publish) # 获取到外键关联的数据对象 多对多中: print(book_obj.authors) # 已经跨到第三张表了

1|01. 一对多

1|0(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

1|0(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)

1|0(3)删

  • 删除出版社表中主键为1的出版社
models.Publish.objects.filter(pk=1).delete() # 默认就是级联删除 级联更新

1|02. 多对多表数据的增删改

1|0(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的作者

1|0(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))

1|0(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)

1|0(4)清空

  • 使用clear()方法

  • 删除某个数据在第三张表中的所有记录

  • clear清空书籍相关所有记录 括号内不需要传递参数

book_obj = models.Book.objects.filter(pk=2).first() book_obj.authors.clear() # 删除主键为2的图书在第三张表中的所有记录

1|98. 跨表查询

  • 两种查询方式:
    • 通过对象查询,运用子查询原理
    • 通过双下划线,运用联表原理

1|0(1)正反向查询

正反向查询 关系字段即外键字段在表1中 由表1查表2的内容就是正向 否则 就是反向 正向查询按字段 反向查询按表名小写 + _set """ 什么时候需要加all() 当正向查询点击外键字段数据有多个的情况下 需要.all() app01.Author.None 一旦看到该结果 只需要加.all()即可 在写orm语句的时候跟你写sql语句一样 不要想着一次性写完 写一点查一点再写一点 """ """ 什么时候反向查询的时候表名小写需要加_set 一对多 多对多 一对一不需要加_set """

1|01. 通过对象查询,即子查询方式

1|0(1)原理

  • 子查询(就是分步操作的来查询)

1|0(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)

1|02. 双下划线式联表查询

1|0(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表给连接起来组成一张大表了。

1|0(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)

1|03. 三表及以上联表查询实例:

  • 通过外键关系,以顺藤摸瓜式的思想,从一张表到其他表。
查询书籍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)

__EOF__

本文作者BigSun丶
本文链接https://www.cnblogs.com/Mcoming/p/11945533.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   BigSun丶  阅读(155)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示