Django ORM查询

Django提供了一套非常方便的类似SqlAlchemy ORM的通过对象调用的方式操作数据库表的ORM框架。

Django ORM操作主要分为以下几类:

  1. 增:向表内插入一条数据
  2. 删:删除表内数据(物理删除)
  3. 改:update操作更新某条数据
  4. 查:基本的表查询(包括多表、跨表、子查询、联表查询)

其中比较复杂的是表查询。下面分类讲解这几种操作方式。

1 增 – 向表内插入一条数据

关于新增记录的操作这里分为两种方式:

  • 第一种方式,通过模型对象的save()方法:
userObj=User()
userObj.username= request.data.get('username')
# userObj.password= make_password(request.POST.get('password'),None,'pbkdf2_sha256')  # 创建django密码,第三个参数为加密算法
userObj.set_password(request.data.get('password'))  # 创建django密码,第三个参数为加密算法
userObj.name= request.data.get('name')
userObj.phone= request.data.get('phone')
userObj.email= request.data.get('email')
userObj.create_name= request.data.get('create_name')
userObj.update_name= request.data.get('update_name')
userObj.is_superuser= 0
print(userObj.username)
print('username %s' % (userObj.username))
print('password %s' % (userObj.password))
userObj.save()

这种方式通过线创建一个模型对象,赋值,最后调用模型的 .save()方法的方式向数据库插入一条数据。

  • 第二种方式,通过objects.create的方式直接新增,类似一种缩略的方式,比较简单
res = models.User.objects.create(username='admin',make_password='123456',register_time=datetime.datetime.now())
print(res)

2 删 – 删除表内数据(物理删除)

django删除表数据是通过.delete()方法,举例:

如果我们只删除 user表 主键为1的记录: ret = models.User.objects.get(pk=1).delete()
上述是只删一条记录,删除多条记录类似: ret = models.User.objects.filter(pk__gt=1).delete()

这样我们可以批量删除user表中主键值大于1的其他所有记录。

需要提醒的是,这种方式属于物理删除,删除后不可恢复,如需逻辑删除,参考下面 update的方式。

3 改 – update操作更新某条数据

django ORM 的改操作,这里分为三种方式。我们先按单记录的更新讲解,批量更新类似:

  • 第一种,指定更新字段更新:
ret = models.User.objects.get(pk=1).update(username='admin',password='123456')
  • 第二种,通过 Json 更新:
object = {'username':'admin','password':'123456'}
ret = models.User.objects.get(pk=1).update(**object)
  • 第三种,类似增操作,直接通过.save()方法更新整条记录
userObj=User()
userObj.id= request.data.get('id')
userObj.username= request.data.get('username')
# userObj.password= make_password(request.POST.get('password'),None,'pbkdf2_sha256')  # 创建django密码,第三个参数为加密算法
userObj.set_password(request.data.get('password'))  # 创建django密码,第三个参数为加密算法
userObj.name= request.data.get('name')
userObj.phone= request.data.get('phone')
userObj.email= request.data.get('email')
userObj.create_name= request.data.get('create_name')
userObj.update_name= request.data.get('update_name')
userObj.is_superuser= 0
print(userObj.username)
print('username %s' % (userObj.username))
print('password %s' % (userObj.password))
userObj.save()

这种方式不太建议用,需要注意数据的完整性。

4 查 – 基本的表查询(包括多表、跨表、子查询、联表查询)

4.1 基本查询

需要了解如下方法的使用:

  1. all() 查询所有数据
  2. filter() 带有过滤条件的查询 where
  3. get() 获取单条,查询不到会报错
  4. first()queryset里第一条记录
  5. last()queryset里最后一条记录
  6. values() 指定要获取的字段
models.User.objects.filter(pk=1).values('username','phone')
# 返回 <QuerySet [{'username': 'admin', 'phone': '176****'}]>
  1. values_list() 列表套元祖
 models.User.objects.filter(pk=1).values_list('username','phone')
# 返回 <QuerySet [('admin','176***')]>
  1. distinct() 去重
ret = models.User.objects.filter(pk=1).distinct()

需要注意,这里去重是针对整条数据的去重,主键不一样也不会去重

  1. order_by() 排序
ret = models.User.objects.order_by('username')# 默认升序
ret = models.User.objects.order_by('-username')# 降序
  1. reverse() 反转,前提已排序
ret = models.User.objects.order_by('username').reverse()# 默认升序
ret = models.User.objects.order_by('-username').reverse()# 降序
  1. count() 当前查询条件的记录数
ret = models.User.objects.filter(pk=1).count()
  1. exclude() 排除 ,相当于查询条件不等于
ret = models.User.objects.exclude(pk=1)
  1. exists() 记录是否存在,不太实用,不过多讲

4.2 双下划线查询条件

django不支持 类似:>=,<=等查询判断方式,但提供了一套很好用的方法:

  • __gt <=> 大于:
    ret = models.User.objects.filter(id__gt=1)#查询id>1的记录

  • __lt <=> 小于: ret = models.User.objects.filter(id__lt=1)#查询id<1的记录

  • __gte <=> 大于等于: ret = models.User.objects.filter(id__gte=1)#查询id>=1的记录

  • __lte <=> 小于等于: ret = models.User.objects.filter(id__lte=1)#查询id<=1的记录

  • __in <=> 条件是否归属所给的选择: ret = models.User.objects.filter(id__in=[1,2])#查询id=1或id=2的记录

  • __range <=> 范围: ret = models.User.objects.filter(id__range=[1,3])#查询1<=id<=3的记录

  • __contains <=> 模糊查询 ,区分大小写: ret = models.User.objects.filter(username__contains='a')#查询 username like '%a%'的记录

  • __icontains <=> 模糊查询 ,不区分大小写: ret = models.User.objects.filter(username__icontains='a')#查询 username like '%a%'的记录

  • __startswith <=> 模糊查询 ,指定内容开始: ret = models.User.objects.filter(username__icontains='a')#查询 username like 'a%'的记录

  • __endswith <=> 模糊查询 ,指定内容结束: ret = models.User.objects.filter(username__icontains='a')#查询 username like '%a'的记录

注意__contains__icontains__startswith__endswith这些模糊查询性能很低,生产环境不建议使用。


4.3 逻辑查询:or、and、not

涉及概念:Django的Q对象

4.3.1 Q对象

Q对象实例化后能够增加各个条件之间的关系,而且这种写法用在你不知道用户到底传入了多少个参数的时候很方便。

  1. 比如默认情况下filter()里面每个字段的连接都是&,我们使用Q对象通常都是让它变成|,来进行查询 。
from django.db.models import Qquery = Q()
q1 = Q()
q1.connector = "AND"  # 连接的条件是AND 代表就是& 
q1.children.append(("email", "280773872@qq.com")) # email代表的是数据库的字段
q1.children.append(("password", "666"))# 等同于:email="280773872@qq.com" & password="666"
q2 = Q()
q2.connector = "AND"  # 同样q2对象连接条件也是AND 
q2.children.append(("username", "fe_cow")) # 同样数据库里username字段
q2.children.append(("password", "fe_cow666"))# 等同于:username="fe_cow" & password="fe_cow666"
query.add(q1, "OR") 
query.add(q2, "OR")# query目前里面的符合条件结果就是: (email="280773872@qq.com" & password="666") |  (username="fe_cow" & password="fe_cow666")
userinfo_obj = models.UserInfo.objects.filter(query).first()

filter()过滤器的方法中关键字参数查询,会合并为And(),需要进行or查询,使用Q()对象,Q对象django.db.models.Q用于封装一组关键字参数,这些关键字参数与比较运算符中的相同。

  • Q对象可以使用&(and)、|(or)操作符组合起来,当操作符应用在两个Q对象时,会产生一个新的Q对象。
list.filter(pk__lt=6).filter(bcomment__gt=10) 
list.filter(Q(pk__lt=6) | Q(bcomment__gt=10))
  • 使用~操作符在Q对象前表示取反: list.filter(~Q(pk__lt=6))

  • 可以使用&|~结合括号进行分组,构造出复杂的Q对象

4.3.2 or、and、not
import os
import djangoos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'salary.settings')
django.setup(set_prefix=False)from employee.models import Employees  # 这一行必须在`os.environ.setdefault`之后,先把配置、环境变量准备好后才能import
from django.db.models import Q
# emps = Employees.objects.all()  # 懒查询,只有后面对查询结构有引用时,才会驱动真正的查询
# print(emps)  # 查询集mgr = Employees.objects
# AND查询: 五种方式
x = mgr.filter(pk__gt=10005, pk__lt=10010)
print(x)
y = mgr.filter(pk__gt=10005).filter(pk__lt=10010)
print(y)
z = mgr.filter(pk__gt=10005) & mgr.filter(pk__lt=10010)
print(z)
# Django的Q对象
xx = mgr.filter(Q(pk__gt=10005) & Q(pk__lt=10010))
yy = mgr.filter(Q(pk__gt=10005), Q(pk__lt=10010))# OR查询: 三种方式
x = mgr.filter(pk__in=[10005, 10010])
print(x)
y = mgr.filter(pk=10005) | mgr.filter(pk=10010)
print(y)
z = mgr.filter(Q(pk=10005) | Q(pk=10010))# NOT查询:
x = mgr.exclude(pk=10005)
print(x)
y = mgr.filter(~(Q(pk__gt=10005) & Q(pk__lt=10010)))
print(y)

4.3.3 集合查询

# 聚合
from django.db.models import Max, Min, Count, Sum, Avg
x = mgr.filter(pk__gt=10008).count()  # 将所有数据看做一行出结构
print(x)  # 单值
# aggregate聚合函数:出统计函数的结果,返回字典,默认key命名为`字段名_聚合函数名`
y = mgr.filter(pk__gt=10008).aggregate(Count("pk"), Max("pk"), Min("pk"), sm_pk=Sum('pk'), avg_pk=Avg('pk'))  # 可以给聚合查询结果起别名
print(y)
# 结果:{'sm_pk': 120174, 'avg_pk': 10014.5, 'pk__count': 12, 'pk__max': 10020, 'pk__min': 10009}
# annotate聚合函数:这个聚合函数会分组,没有指定分组使用pk分组,行行分组。返回结果集
z = mgr.filter(pk__gt=10013).annotate(Count("pk"), Max("pk"), Min("pk"), sm_pk=Sum('pk'), avg_pk=Avg('pk'))
print(z)
xx = mgr.filter(pk__gt=10013).values('gender').annotate(c=Count("pk")).values("c")  # 第一个values控制分组,第二个values控制投影
print(xx)

4.4 多表查询

4.4.1 多对多查询

我们先定义两张表:User表(用户表),Artile表(文章表),一篇文章可以被多个用户关注,一个用户也可以关注多篇文章,二者是多对多的关系。

from django.db import models
import datetimeclass Artile(models.Model):"""title: 标题sub_title: 子标题content: 内容"""def __str__(self):return self.titletitle = models.CharField(max_length=250,default='',verbose_name='标题')sub_title = models.CharField(max_length=250,default='',verbose_name='子标题')content = models.CharField(max_length=2000,default='',blank=True,verbose_name='内容')# 与User表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表users = models.ManyToManyField(to='User', )create_time = models.DateTimeField(default=datetime.datetime.now(),verbose_name='创建时间')create_name = models.CharField(max_length=20,verbose_name='创建人')update_time = models.DateTimeField(default=datetime.datetime.now(),blank=True,verbose_name='更新时间')update_name = models.CharField(max_length=20,verbose_name='更新人',blank=True,)is_delete = models.IntegerField(default=0,verbose_name='删除状态',blank=True,) # 逻辑删除 0 正常 1:删除class Meta:verbose_name = "文章"verbose_name_plural = verbose_nameapp_label = 'webApi'
from django.db import models
import datetime
#引入系统用户的分类
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.hashers import make_password #密码加密#userProfile继承AbstractUser分类,进行拓展
class User(AbstractUser):"""name: 昵称account: 用户名pwd: 密码phone:手机号email:邮箱avator:头像group_id:归属组"""def __str__(self):return self.accountname = models.CharField(max_length=20,default='',verbose_name='昵称')phone = models.CharField(max_length=20,default='',blank=True,verbose_name='手机号')email = models.CharField(max_length=20,default='',blank=True,verbose_name='邮箱')avator = models.CharField(max_length=200,default='',blank=True,verbose_name='头像')group_id = models.CharField(max_length=50,default='',blank=True,verbose_name='组')create_time = models.DateTimeField(default=datetime.datetime.now(),verbose_name='创建时间')create_name = models.CharField(max_length=20,verbose_name='创建人')update_time = models.DateTimeField(default=datetime.datetime.now(),blank=True,verbose_name='更新时间')update_name = models.CharField(max_length=20,verbose_name='更新人',blank=True,)is_delete = models.IntegerField(default=0,verbose_name='删除状态',blank=True,) # 逻辑删除 0 正常 1:删除# blank=True, 可选字段class Meta:verbose_name = "用户"verbose_name_plural = verbose_namedef __str__(self):return self.username# 明文密码转加密def set_password(self, password):print('set_password %s' % (password))self.password = make_password(password,'jxy','pbkdf2_sha256')# 验证密码是否匹配def check_password(self, password):print('password: %s' % (password))print('check_password: %s' % (make_password(password,'jxy','pbkdf2_sha256')))print('self.password: %s' % (self.password))return self.password == make_password(password,'jxy','pbkdf2_sha256')

注意我们在Artile表中定义的users = models.ManyToManyField(to='User'),通过这种定义方式,我们在 Artile表与User表之间创建了一个针对这两张表的关系表。
接下来我们向这张关系表中添加几条关系。比如,我们将 Artile表主键为1的一条记录,添加User表 主键为1,2两条关系。

user1 = models.User.object.filter(pk=1).first()
user2 = models.User.object.filter(pk=2).first()artile1 = models.Artile.object.filter(pk=1).first()
artile1.users.add(user1,user2)# 方法二
userSet = models.User.object.filter(pk__in=[1,2]).all()
artile1.users.add(*userSet)

这样便在关系表中创建了 Artile表主键为1的记录 与 User表 主键为1,2的两条关系。
另外清除关系绑定用法类似,使用remove替代add:

artile1 = models.Artile.object.filter(pk=1).first()
userSet = models.User.object.filter(pk__in=[1,2]).all()
artile1.users.remove(*userSet) #解绑指定关系
artile1.users.clear() #清空所有关系

多对多查询:

  • 正向查询,例如查询Artile表第一条记录有哪些用户关注:
artile1 = models.Artile.object.filter(pk=1).first()
print(artile1.users.all().values('username')) # 打印关注Artile表第一条记录的用户名称
  • 逆向查询,例如查询User表第一条记录关注过哪些Artile:
user1 = models.User.object.filter(pk=1).first()
print(user1.artile__set.all().values('title')) # 打印User表第一条记录关注的文章名称
4.4.2 一对多查询

参考:
https://juejin.cn/post/6974298891353063431

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/109284.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字化 | 智能电子日历

想要一款随时随地都能掌握日期的电子日历吗&#xff1f; WiFi通信&#xff0c;实时更新&#xff0c;超低功耗&#xff0c;可充电&#xff0c;超长续航&#xff0c;电子纸&#xff0c;黑白红三色显示的电子日历&#xff0c;就是你的最佳选择&#xff01; 无论是在办公室、家中或…

QCC51XX-QCC30XX系列开发教程(实战篇) 之 12.4-空间音频手机侧和耳机侧接口设计时序图

查看全部教程开发请点击:全网最全-QCC51xx-QCC30xx(TWS)系列从入门到精通开发教程汇总(持续更新中) ==================================================================== 版权归作者所有,未经允许,请勿转载。 ==========================================

自建应用-企业微信-侧边栏开发配置

企业微信侧边栏开发配置 配置侧边栏配置后效果图js-sdk 配置侧边栏 配置后效果图 js-sdk https://developer.work.weixin.qq.com/document/path/91789

“系统重要性银行”光环下,南京银行的重重忧思

撰稿|行星 来源|贝多财经 南京银行喜忧参半&#xff0c;提名系统重要性银行&#xff0c;还面临信誉老题、业绩新题难解的问题。 近期&#xff0c;中国人民银行、国家金融监督管理总局开展了2023年度我国系统重要性银行评估&#xff0c;认定20家国内系统重要性银行&#xff0…

如何分析K8S中的OOMKilled问题(Exit Code 137)

什么是 OOMKilled Kubernetes 错误&#xff08;Exit Code 137&#xff09; 当 Kubernetes 集群中的容器超过其内存限制时&#xff0c;Kubernetes 系统可能会终止该容器并显示“OOMKilled”错误&#xff0c;这表明该进程由于内存不足而被终止。此错误的退出代码是 137。 如果遇…

代码随想录算法训练营第二十五天丨 回溯算法part03

39. 组合总和 思路 题目中的无限制重复被选取&#xff0c;提示&#xff1a;1 < candidates[i] < 200。 本题和77.组合 (opens new window)&#xff0c;216.组合总和III (opens new window)的区别是&#xff1a;本题没有数量要求&#xff0c;可以无限重复&#xff0c;但…

记录:移动设备软件开发(layout六大布局)

目录 前言layoutLinearLayout线性布局LinearLayout的常用属性Android&#xff1a;orientation属性Android&#xff1a;gravity属性 TableLayout表格布局TableLayout的常用属性collapsecolumns属性shrinkcolums属性stretchcoumns属性 RelativeLayout相对布局Absolute Layout绝对…

构造shiro poc

攻击shiro思路 伪造加密过程 shiro在容器初始化的时候会实例化CookieRememberMeManager对象&#xff0c;并且设置加密解密方式 实例化时调用父类构造方法&#xff0c;设置加密方式为AES&#xff0c;并且设置key 看下调用栈 <init>:109, AbstractRememberMeManager (org…

12JVM基础

五、JVM 17、JVM基础 说一下堆栈的区别&#xff1f; 功能方面&#xff1a;堆是用来存放对象的&#xff0c;栈是用来执行程序的。 共享性&#xff1a;堆是线程共享的&#xff0c;栈是线程私有的。 空间大小&#xff1a;堆大小远远大于栈。队列和栈是什么&#xff1f;有什么区别…

python数据挖掘从入门到实战

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

typeScript 类型什么时候使用any?

在类型不确定的情况下&#xff0c;使用 any 是一种选项&#xff0c;但通常不是最佳选择。使用 any 类型会让你失去 TypeScript 提供的类型安全性和编译时检查。以下是几种处理类型不确定性的更好方法&#xff1a; 联合类型&#xff08;Union Types&#xff09;: 如果一个值可能…

电商独立站小程序开发方案

随着移动互联网的迅速发展&#xff0c;电商行业也逐渐向小程序平台转移。开发一款电商小程序对于拓展销售渠道、提高用户体验、增加用户忠诚度等方面都有着重要的意义。本文将围绕电商小程序的开发背景、需求分析、技术选型、开发流程、风险控制、商业模式和市场前景等方面进行…

python代码调用文件或数据库中保存的脚本

这里采用的读取excel 1、先写一个测试方法 def demo5():import xlrdimport randomwb xlrd.open_workbook("code.xls")st wb.sheet_by_index(0)code st.cell_value(0, 0)list ["6666", asd, 1ad23, 1f23, 12g3, 1b3, 12r3]code2 st.cell_value(0, 1)…

[游戏开发][Unity] UnityWebRequest中断续传

UnityWebRequest和WWW加载的底层原理还是Http 断点续传的原理 UnityWebRequest第一次请求Url&#xff0c;如果请求成功&#xff0c;从头文件里把文件总长度读出来 long totalLength long.Parse(huwr.GetResponseHeader("Content-Length")) 由于文件是边下边写入的&a…

JVS规则引擎及智能BI又更新新功能啦!赶紧来试试

规则引擎更新功能 新增: 1.复合变量新增排序、排名功能 可以按照特定的顺序对数据进行排列&#xff0c;确定规则的优先级&#xff0c;可以提高数据处理效率&#xff0c;帮助分析人员更好地了解数据分布和趋势。 2.决策流新增动态日志功能 动态日志可以记录规则执行的过程和…

Jmeter性能测试(压力测试)

1.先保存 2.添加请求&#xff08;即添加一个线程组&#xff09; 3.添加取样器&#xff08;在线程组下面添加一个http请求&#xff09; 场景1&#xff1a;模拟半小时之内1000个用户访问服务器资源&#xff0c;要求平均响应时间在3000毫秒内&#xff0c;且错误率为0&#xff0…

【Linux初阶】多线程4 | POSIX信号量,基于环形队列的生产消费模型,线程池,线程安全的单例模式,STL-智能指针和线程安全

文章目录 ☀️一、POSIX信号量&#x1f33b;1.引入&#x1f33b;2.信号量的概念&#x1f33b;3.信号量函数 ☀️二、基于环形队列的生产消费模型&#x1f33b;1.理解环形队列&#x1f33b;2.代码案例 ☀️三、线程池☀️四、线程安全的单例模式&#x1f33b;1.单例模式与设计模…

如何系统性的学习报关知识

学习报关知识的方法如下&#xff1a; 学习法律法规&#xff1a;报关是受国家法律法规约束的&#xff0c;因此学习法律法规是非常重要的。可以去中华人民共和国海关总署官网查询相关法规。 学习关税分类&#xff1a;了解不同商品的分类和税率&#xff0c;可以去海关总署官网查询…

共享盘文件如何防止别人恶意删除

在如今数字化信息交流的社会中&#xff0c;共享文件已经成为很常见的设置了。然而&#xff0c;对于共享盘文件而言&#xff0c;恶意删除是一种常见的安全威胁&#xff0c;因此用户需要掌握一些方法来保护自己的文件安全。本文将介绍防止别人恶意删除共享盘文件的方法&#xff0…

mybaits动态代理实验

实验目的 掌握MyBaits动态代理的使用log4j日志的使用Lombk的使用单元测试的使用SqlSessionFactory单例模式预处理语句的使用 实验内容 完成学生表的增删改查&#xff0c;学生表信息如下 CREATE TABLE tb_student( sno INT AUTO_INCREMENT PRIMARY KEY, student_name VAR…