一、ORM常用关键字

# 关键概览
1.create()
2.filter()
3.first() last()
4.update()
5.delete()
6.all()
7.values()
8.values_list()
9.distinct()
10.order_by()
11.get()
12.exclude()
13.reverse()
14.count()
15.exists()

# 1.create()  创建数据并直接当前创建的数据对象
res = models.UserInfo.objects.create(name='almra', age=24)

  

# 2.filter() 根据条件筛选数据 结果是QuerySet [数据对象1,数据对象2]
res = models.UserInfo.objects.filter(name='amira') # 括号没有写默认全部筛选 括号内支持多个条件 默认是and

  

# 3.first() last()  QuerySet支持索引取值但只是支持正数 并且orm不建议使用索引
res = models.UserInfo.objencts.filter()[1] # 查询到列表对应的数据 对应数据不存在会报错
res = models.UserInfo.objects.filter().first() # 查询到列表第一个数据 对应数据不存在不会报错返回None

  

# 4.update()  更新数据
res = models.UserInfo.objects.filetr().update() # 批量更新
res = models.UserInfo.objects.filetr(id=1).update() # 自定义更新

  

# 5.delete()  删除数据(批量删除)
models.UserInfo.objects.filter().delete() # 批量删除
models.UserInfo.objects.filter(id=1).delete() # 单个删除

  

# 6.all()  查询所有数据 结果是QuerySet [数据对象1,数据对象2]
res = models.UserInfo.objects.all()

  

# 7.values()  根据指定字段获取数据    结果是QuerySet [{},{},{},{}]
res = models.UserInfo.objects.all().values('name')
res = models.UserInfo.objects.filter().values()
res = models.UserInfo.objects.values()

  

# 8.values_list()  根据指定字段获取数据 结果是QuerySet [(),(),(),()]
res = models.UserInfo.objects.all().values_list('name','age')

  

# 9.distinct()   去重 数据一定要一模一样才可以 如果有主键肯定不行
res = models.UserInfo.objects.values('name','age').distinct()

  

# 10.order_by()  根据指定条件排序 默认是升序 字段前面加负号就是降序
res = models.UserInfo.objects.all().order_by('age')

  

# 11.get()   根据条件筛选数据并直接获取到数据对象  一旦条件不存在会直接报错 不建议使用
res = models.UserInfo.objects.get(pk=1)

  

# 12.exclude()  取反操作
res = models.UserInfo.objects.exclude(pk=1)

  

# 13.reverse()  颠倒顺序(被操作的对象必须是已经排过序的才可以)
res1 = models.UserInfo.objects.all().order_by('age').reverse()

  

# 14.count()  统计结果集中数据的个数
res = models.User.objects.all().count()

  

# 15.exists()  判断结果集中是否含有数据 如果有则返回True 没有则返回False
res = models.User.objects.all().exists()

  

二、ORM查询SQL语句的方法

方式1:raw()

models.User.objects.raw('select * from app01_user;')

  

方式2:cursor()

from django.db import connection
cursor = connection.cursor()
cursor.execute('select name from app01_user;')
print(cursor.fetchall())

 

三、神奇的双下划线查询

只要还是queryset对象就可以无限制的点queryset对象的方法
比如:queryset.filter().values().values_list().filter()....

  

1.查询年龄大于18岁的用户数据/年龄小于38岁的用户数据

res = models.Users.objects.filter(age__gt=18)  # 大于18岁
res = models.Users.objects.filter(age__lt=38) # 小于18岁

  

2.查询年龄大于等于18岁的用户数据/年龄小于等于38岁的用户数据

res = models.Users.objects.filter(age__gte=18)  # 大于等于18岁
res = models.Users.objects.filter(age__lte=38) # 小于等于18岁

  

3.查询年龄是18岁或28岁或38岁的用户数据

res = models.User.objects.filter(age__in=(18, 28, 38))

  

4.查询年龄在18岁到38岁之间所有用户数据

res = models.User.objects.filter(age__range=(18, 38))

  

5.查询名名字中含有字母j的用户数据

res = models.User.objects.filter(name__contains='j')  # 只查j不查J字母
res = models.User.objects.filter(name__incontains='j') # J,j都会查出来

  

6.查询注册年份是2022年的用户数据

res = models.User.objects.filter(register_time__year=2022)

  

四、ORM外键字段创建

1.ORM外键字段创建理论铺垫

MySQL外键关系
一对多:外键字段在多的一方
多对多:外键字段统一建在第三张关系表
一对一:建议放在查询频率较高的表
ORM确定外键关系
一对多:外键字段在多的一方 跟MySQL一致
多对多:外键字段建在查询频率较高的表(内部自动创建第三张表)
一对一:建议放在查询频率较高的表 跟MySQL一致
ORM创建外键字段代码语句
针对一对多和一对一同步到表中之后会自动加_id的后缀
publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
author_detail = models = models.OneToOneFiled(to='AuthorDetail', on_delete=models.CASCADE)
针对多对多不会在表中展示而是创建第三张表
authers = models.ManyToManyField(to='Author')

2.ORM外键字段创建相关操作

# 针对一对多 插入数据可以直接填写表中的实际字段
models.Book.objects.create(title='编程基础教学', price=888.88, publish_id=1)
models.Book.objects.create(title='编程进阶教学', price=999.99, publish_id=1)
# 针对一对多 插入数据也可以填写表中的类中字段
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Book.objects.create(title='高级编程指导书', price=1000, publish=publish_obj)

  

'''一对一与一对多 一致'''
既可以传数字也可以传对象
# 针对多对多关系绑定
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.add(1) # 在第三张关系表中给当前书籍绑定作者
book_obj.authors.add(2, 3)
book_obj = models.Book.objects.filter(pk=4).first()
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first()
book_obj.authors.add(author_obj1)
book_obj.authors.add(author_obj1, author_obj2)
book_obj = models.Book.objects.filter(pk=1).first()

  

book_obj.authors.set((1, 3))  # 修改关系
book_obj.authors.set([2, ]) # 修改关系
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first()
book_obj.authors.set((author_obj1,))
book_obj.authors.set((author_obj1, author_obj2))
book_obj.authors.remove(2)
book_obj.authors.remove(1, 3)
book_obj.authors.remove(author_obj1,)
book_obj.authors.remove(author_obj1,author_obj2)
book_obj.authors.clear()

  

二、多对多三种创建方式

1.全自动创建
class Book(models.Model):
title = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Authors', on_delete=models.CASCADE)
class Authors(models.Model):
name = models.CharField(max_length=32) # 优势:自动创建第三张表 并提供了add、remove、set、clear四种操作
# 劣势:第三张表无法创建更多的字段 扩展性比较差

  

2.手动创建
class Book(models.Moldel):
title = model.CharField(max_length=32)
class Author(models.Model):
name = moldel.CharField(max_length=32)
class Book2Author(models.Model):
book = models.ForeignKey(to='Book',on_delete=models.CASCADE)
others = models.CharField(max_length=32)
join_time = models.DateField(auto_now_add=True) # 优势:第三张表自己创建 扩展性强
# 劣势:编写繁琐并不再支持add、remove、set、clear以及正反向概念

  

3.半自动创建
class Book(models.Model):
title = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Author',
through='Book2Author',
through_fields=('book', 'author')
) class Author(models.Model):
name = models.CharField(max_length=32) class Book2Author(models.Model):
book = models.ForeignKey(to='Book', on_delete=models.CASCADE)
author = models.ForeignKey(to='Author', on_delete=models.CASCADE)
others = models.CharField(max_length=32)
join_time = models.DateField(auto_now_add=True) # 优势:第三张表完全由自己创建 扩展性强 正反向概念依然清晰可用
# 劣势:编写繁琐不再支持add、remove、set、clear

  

五、多表查询(基于对象和双下划线)

1.ORM跨表查询理论

MySQL跨表查询
子查询:分布操作(将一条SQL语句用括号括起来当作另外一条SQL语句的条件)
连表操作:先整合多张表之后基于单表查询即可('inner'/left/right/union join) 正反向查询(重要)
正向:由外键字段所在的表数据查询关联的表查询
反向:无外键字段的表数据查询关联的表数据查询
# 技巧:核心就看外键字段在不在当前数据所在的表中 ORM跨表查询
正向查询按外键字段
反向查询按表名小写

  

2.基于对象的跨表查询

# 1.查询主键为1的书籍对应的出版社名称
# 先根据条件获取数据对象
book_obj = models.Book.objects.filter(pk=1).first()
# 再判断正反向的概念 由书查出版社 外键字段在书所在的表中 所以是正向查询
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())
print(book_obj.authors.all().values('name'))

  

# 3.查询almira的电话号码
author_obj = models.Author.objects.filter(name='almira').first()
print(author_obj.author_detail.phone)

  

# 4.查询北方出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='新疆维吾尔出版社').first()
print(publish_obj.book_set) # app01.Book.None
print(publish_obj.book_set.all())

  

# 5.查询almira写过的书籍
author_obj = models.Author.objects.filter(name='almira').first()
print(author_obj.book_set) # app01.Book.None
print(author_obj.book_set.all())

  

# 6.查询电话号码是18988998899的作者姓名
author_detail_obj = models.AuthorDetail.objects.filter(phone=18988998899).first()
print(author_detail_obj.author)
print(author_detail_obj.author.name)

  

3.基于双下划线的跨表查询

 # 1.查询主键为1的书籍对应的出版社名称
res = models.Book.objects.filter(pk=1).values('publish__name','title')
print(res)

  

# 2.查询主键为4的书籍对应的作者姓名
res = models.Book.objects.filter(pk=4).values('title', 'authors__name')
print(res)

  

 # 3.查询almira的电话号码
res = models.Author.objects.filter(name='almira').values('author_detail__phone')
print(res)

  

# 4.查询北方出版社出版过的书籍名称和价格
res = models.Publish.objects.filter(name='新疆维吾尔出版社').values('book__title','book__price','name')
print(res)

  

# 5.查询almira写过的书籍名称
res = models.Author.objects.filter(name='almira').values('book__title', 'name')
print(res)

  

# 6.查询电话号码是110的作者姓名
res = models.AuthorDetail.objects.filter(phone=110).values('phone', 'author__name')
print(res)

  

4.进阶操作

# 1.查询主键为1的书籍对应的出版社名称
res = models.Publish.objects.filter(book__pk=1).values('name')
print(res)

  

# 2.查询主键为4的书籍对应的作者姓名
res = models.Author.objects.filter(book__pk=4).values('name','book__title')
print(res)

  

# 3.查询almira的电话号码
res = models.AuthorDetail.objects.filter(author__name='almira').values('phone')
print(res)

  

# 4.查询北方出版社出版过的书籍名称和价格
res = models.Book.objects.filter(publish__name='新疆维吾尔出版社').values('title','price')
print(res)

  

# 5.查询almira写过的书籍名称
res = models.Book.objects.filter(authors__name='almira').values('title')
print(res)

  

# 6.查询电话号码是18988998899的作者姓名
res = models.Author.objects.filter(author_detail__phone=18988998899).values('name')
print(res)

  

5.补充说明

# 查询主键为4的书籍对应的作者的电话号码
res = models.Book.objects.filter(pk=4).values('authors__author_detail__phone')
print(res)
res = models.AuthorDetail.objects.filter(author__book__pk=4).values('phone')
print(res)
res = models.Author.objects.filter(book__pk=4).values('author_detail__phone')
print(res)

  

六、聚合查询

聚合函数:Max Min Sun Count Avg
在ORM中支持单独使用聚合函数 用关键字:aggregate from django.db.models import Max, Min, Sum, Avg, Count
res = models.Book.objects.aggregate(Max('price'), Min('price'), Sum('price'), Avg('price'), Count('pk'))
print(res)

  

七、分组查询

如果执行ORM分组查询报错 并且有关键字sql_mode strict mode
移除sql_mode中的only_full_group_by 即可! 代码如下 set global sql_mode='stric_trans_tables';

  

1.统计每一本书的作者个数

res = models.Book.objects.annotate(author_num=Count('authors_pk')).values('title', 'author_num')
print(res)

  

2.统计出每个出版社卖出的最便宜的书的价格

res = models.Publish.objects.annotate(min_price=Min('book_price')).values('name', 'min_price')
print(res)

  

3.统计不止一个作者的书

res = models.Author.objects.annotate(totalprice=Sum('book__price'),count_book=Count('book_pk')).values('name','totalprice','count_book')
print(res)

  

# 按照表名分组
models.表名.objects.annotate()
# 按照values括号内指定的字段分组
models.表名.objects.values('字段名').annotate()

  

res = models.Book.objects.values('publish_id').annotate(count_pk=Count('pk')).values('publish_id','count_pk')
print(res)

  

八、F与Q查询

1.什么是F查询?
F查询:同一张表格的不同字段之间的查询
当查询条件不是明确的 也需要从数据库中获取 就需要使用F查询 2.什么是Q查询?
Q查询:需要复杂的逻辑关系的时候使用Q查询
逗号默认是and,处理不了or not 这样的更复杂查询条件 这时Q查询用上排场了 | 表示取或or
& 表示取且and
~ 表示取反not

  

1.查询库存数量大于卖出的书籍数量

from django.db.models import F
res = models.Book.objects.filter(stock__gt=F('sold'))
print(res)

  

2.将所有书的价格涨800

from django.db.models import F
models.Book.objects.update(price=F(price) + 800)

  

3.将所有书的名称后面追加爆款

from django.db.models import F
from django.db.models.functions import Concat
from django.db.models import Value models.Book.objects.update(title=Concat(F('title'),Value('爆款')))

  

4.查询主键是1或者大于2000的书籍

from django.db.models import Q
res = models.Book.objects.filter(Q(pk=1) | Q(price__gt=2000))

  

九、Q查询进阶操作

from django.db.models import Q
q_obj = Q() # 1.产生Q对象
q_obj.connector = 'or' # 默认多个条件的连接是and可以修改为or
q_obj.children.append(('pk', 1)) # 2.添加查询条件
q_obj.children.append(('price__gt', 2000)) # 支持添加多个
res = models.Book.objects.filter(q_obj) # 查询支持直接填写q对象
print(res)

  

十、ORM查询优化

1.ORM的查询默认都是惰性查询

如果你仅仅只是书写了ORM语句  没有用该语句所查询出来的参数
那么ORM会自动识别 直接不执行 这个性质可以提升效率 节省资源

  

2.only与defer

res = models.Book.objects.only('title', 'price')  # only关键字查询详解
print(res) # 结果是queryset对象[数据对象、数据对象]
for obj in res:
print(obj.title) # 点击括号内填写的字段 不走SQL查询语句
print(obj.publish_time) # 可以执行括号内没有的字段并获取数据 但是会走SQL查询语句

  

res = models.Book.objects.defer('title', 'price')  # defer关键字查询详解
print(res) # 结果是queryset对象[数据对象、数据对象]
for obj in res:
print(obj.title) # 点击括号内填写的字段 走SQL查询语句
print(obj.publish_time) # 点击括号内没有的字段获取数据 不会走SQL查询语句

  

3.selected_related与prefetch_related

res = models.Book.objects.selected_related('authors')  # selected_related相当于连表查询 不支持多对多
for obj in res:
print(res)

  

res = models.Book.objects.prefetch_related('publish')  # prefetch_related相当于子查询
for obj in res:
print(obj.publish.name)

  

十一、ORM批量操作数据(ORM操作优化)

关键字:
bulk_create() # 批量创建数据
bulk_update() # 批量更新数据

  

def ab_bk_func(request):
book_obj_list = [] # 可以用列表生成式[... for i in ... if ...]
for i in range(1, 100000):
book_obj = models.Books01(title='第%s本书' % i) # 单纯的用类名加括号产生对象
book_obj_list.append(book_obj)
models.Books01.objects.bulk_create(book_obj_list) # 批量插入数据
"""使用orm提供的批量插入操作 5s 10万条左右"""
book_queryset = models.Books01.objects.all() # 查询出所有的表中并展示到前端页面
return render(request, 'BkPage.html', locals())

  

十二、ORM常用字段

1.AutoFiled(primary_key=True)  # 主键
2.CharField(max_length=32) # 字符
3.IntegerField # 整型
4.BigIntegerField # 大整型
5.DecimalField(max_digits=8, decimal_places=2) # 十进制字段
6.DateField(auto_now, auto_now_add) # 年月日
7.DateTimeField(auto_now, auto_now_add) # 年月日时分秒
8.BooleanField # 传布尔值自动存0或1
9.TextField # 存储大段文本
10.EmailField # 存储邮件格式数据
11.FileField # 传文本对象 自动保存到提前配置好的路径下并保存路径信息

  

# 可以自定义字段
class MyCharField(models.Field):
def __init__(self,max_length, *args, **kwargs):
self.max_length = max_length
super().__init__(max_length=manx_length, *args, **kwargs) def db_type(self, connection):
return 'char(%s)' % self.max_length class User(models.Model):
name = models.CharField(max_length=32)
info = MyCharField(max_length=64)

  

十三、ORM常用字段参数

primary_key  # 主键
verbose_name # 注释
max_length # 字段长度
max_digits # 小数总共多少位
decimal_places # 小数点后面的位数
auto_now # 每次操作数据自动更新事件
auto_now_add # 首次创建自动更新事件 后续不会自动更新
null # 允许字段为空
default # 字段默认值
unique # 唯一值
db_index # 给字段添加索引
choices # 当某个字段的可能性能被列举完全的情况下使用

  

外键字段
to #关联表
to_field # 关联字段
on_delete=models.CASCADE # 级联操作 当主表删除一条数据 从表关联数据同时被删除
on_delete=models.SET_NULL # 当主表删除一条数据 从表关联字段设置为null 定义外键必须可以允许为空
on_delete=models.PROTECT # 当主表删除一条数据 从表关联字段是受保护的外键 所以都不允许删除
on_delete=models.SET_DEFAULT # 当主表删除一条数据 从表关联字段设置为默认值 定义外键必须有一个默认值
on_delete=models.SET() # 当主表删除一条数据 从表关联字段设置为SET()中设置的值
on_delete=models.DO_NOTHING # 什么都不做 一切都看数据库级别的约束

  

最新文章

  1. 为什么很多SaaS企业级产品都熬不过第一年
  2. jQuery1.9之后使用on()绑定 动态生成元素的 事件无效
  3. NoSQl简介(转)
  4. 将NSString转换成UTF8编码的NSString
  5. faster with MyISAM tables than with InnoDB or NDB tables
  6. 笔记本Linux推荐
  7. property和attribute的区别
  8. js 监听整个页面的回车事件
  9. 用jmap分析java程序
  10. Python 列表生成式、生成器、迭代器
  11. OC基础1:一些基本概念
  12. C#中隐式操作CMD命令行窗口
  13. Photoshop图象切片保存为网页HTML(DIV+CSS布局)的方法
  14. jpda
  15. 操作系统:ucore的部分Bug&挑战练习
  16. fail2ban 防止ssh暴力破解
  17. mysqli_fetch_array() ,mysqli_fetch_assoc()遇到的问题
  18. Eclipse 中构建 Maven 项目的完整过程 - SpringBoot 项目
  19. python之全局变量和局部变量
  20. openssl genrsa

热门文章

  1. BBS登录与注册功能的总结
  2. mov eax,dword ptr[0x00aff834] 和 lea eax,[0x00aff834]区别
  3. Vue23 ref属性
  4. Vue02 Node下载安装
  5. win10使用python自动化安装mysql8.0.11
  6. ChatGPT调研分析与应用场域结合构想
  7. JZOJ 5354. 【NOIP2017提高A组模拟9.9】导弹拦截
  8. HTML5基本网页结构以及标签的改变
  9. ArcGIS for Android 开发环境搭建
  10. 重磅!flink-table-store 将作为独立数据湖项目重新加入 Apache