Django model select的多种用法详解


Posted in Python onJuly 16, 2019

《Django model update的各种用法介绍》文章介绍了Django model的各种update操作,这篇文章就是她的姊妹篇,详细介绍Django model select的用法,配以对应MySQL的查询语句,理解起来更轻松。

基本操作

# 获取所有数据,对应SQL:select * from User
User.objects.all()

# 匹配,对应SQL:select * from User where name = '运维咖啡吧'
User.objects.filter(name='运维咖啡吧')

# 不匹配,对应SQL:select * from User where name != '运维咖啡吧'
User.objects.exclude(name='运维咖啡吧')

# 获取单条数据(有且仅有一条,id唯一),对应SQL:select * from User where id = 724
User.objects.get(id=123)

常用操作

# 获取总数,对应SQL:select count(1) from User
User.objects.count()

# 获取总数,对应SQL:select count(1) from User where name = '运维咖啡吧'
User.objects.filter(name='运维咖啡吧').count()

# 大于,>,对应SQL:select * from User where id > 724
User.objects.filter(id__gt=724)

# 大于等于,>=,对应SQL:select * from User where id >= 724
User.objects.filter(id__gte=724)

# 小于,<,对应SQL:select * from User where id < 724
User.objects.filter(id__lt=724)

# 小于等于,<=,对应SQL:select * from User where id <= 724
User.objects.filter(id__lte=724)

# 同时大于和小于, 1 < id < 10,对应SQL:select * from User where id > 1 and id < 10
User.objects.filter(id__gt=1, id__lt=10)

# 包含,in,对应SQL:select * from User where id in (11,22,33)
User.objects.filter(id__in=[11, 22, 33])

# 不包含,not in,对应SQL:select * from User where id not in (11,22,33)
User.objects.exclude(id__in=[11, 22, 33])

# 为空:isnull=True,对应SQL:select * from User where pub_date is null
User.objects.filter(pub_date__isnull=True)

# 不为空:isnull=False,对应SQL:select * from User where pub_date is not null
User.objects.filter(pub_date__isnull=True)

# 匹配,like,大小写敏感,对应SQL:select * from User where name like '%sre%',SQL中大小写不敏感
User.objects.filter(name__contains="sre")

# 匹配,like,大小写不敏感,对应SQL:select * from User where name like '%sre%',SQL中大小写不敏感
User.objects.filter(name__icontains="sre")

# 不匹配,大小写敏感,对应SQL:select * from User where name not like '%sre%',SQL中大小写不敏感
User.objects.exclude(name__contains="sre")

# 不匹配,大小写不敏感,对应SQL:select * from User where name not like '%sre%',SQL中大小写不敏感
User.objects.exclude(name__icontains="sre")

# 范围,between and,对应SQL:select * from User where id between 3 and 8
User.objects.filter(id__range=[3, 8])

# 以什么开头,大小写敏感,对应SQL:select * from User where name like 'sh%',SQL中大小写不敏感
User.objects.filter(name__startswith='sre')

# 以什么开头,大小写不敏感,对应SQL:select * from User where name like 'sh%',SQL中大小写不敏感
User.objects.filter(name__istartswith='sre')

# 以什么结尾,大小写敏感,对应SQL:select * from User where name like '%sre',SQL中大小写不敏感
User.objects.filter(name__endswith='sre')

# 以什么结尾,大小写不敏感,对应SQL:select * from User where name like '%sre',SQL中大小写不敏感
User.objects.filter(name__iendswith='sre')

# 排序,order by,正序,对应SQL:select * from User where name = '运维咖啡吧' order by id
User.objects.filter(name='运维咖啡吧').order_by('id')

# 多级排序,order by,先按name进行正序排列,如果name一致则再按照id倒叙排列
User.objects.filter(name='运维咖啡吧').order_by('name','-id')

# 排序,order by,倒序,对应SQL:select * from User where name = '运维咖啡吧' order by id desc
User.objects.filter(name='运维咖啡吧').order_by('-id')

进阶操作

# limit,对应SQL:select * from User limit 3;
User.objects.all()[:3]

# limit,取第三条以后的数据,没有对应的SQL,类似的如:select * from User limit 3,10000000,从第3条开始取数据,取10000000条(10000000大于表中数据条数)
User.objects.all()[3:]

# offset,取出结果的第10-20条数据(不包含10,包含20),也没有对应SQL,参考上边的SQL写法
User.objects.all()[10:20]

# 分组,group by,对应SQL:select username,count(1) from User group by username;
from django.db.models import Count
User.objects.values_list('username').annotate(Count('id'))

# 去重distinct,对应SQL:select distinct(username) from User
User.objects.values('username').distinct().count()

# filter多列、查询多列,对应SQL:select username,fullname from accounts_user
User.objects.values_list('username', 'fullname')

# filter单列、查询单列,正常values_list给出的结果是个列表,里边里边的每条数据对应一个元组,当只查询一列时,可以使用flat标签去掉元组,将每条数据的结果以字符串的形式存储在列表中,从而避免解析元组的麻烦
User.objects.values_list('username', flat=True)

# int字段取最大值、最小值、综合、平均数
from django.db.models import Sum,Count,Max,Min,Avg

User.objects.aggregate(Count(‘id'))
User.objects.aggregate(Sum(‘age'))

时间字段

# 匹配日期,date
User.objects.filter(create_time__date=datetime.date(2018, 8, 1))
User.objects.filter(create_time__date__gt=datetime.date(2018, 8, 2))

# 匹配年,year
User.objects.filter(create_time__year=2018)
User.objects.filter(create_time__year__gte=2018)

# 匹配月,month
User.objects.filter(create_time__month__gt=7)
User.objects.filter(create_time__month__gte=7)

# 匹配日,day
User.objects.filter(create_time__day=8)
User.objects.filter(create_time__day__gte=8)

# 匹配周,week_day
 User.objects.filter(create_time__week_day=2)
User.objects.filter(create_time__week_day__gte=2)

# 匹配时,hour
User.objects.filter(create_time__hour=9)
User.objects.filter(create_time__hour__gte=9)

# 匹配分,minute
User.objects.filter(create_time__minute=15)
User.objects.filter(create_time__minute_gt=15)

# 匹配秒,second
User.objects.filter(create_time__second=15)
User.objects.filter(create_time__second__gte=15)


# 按天统计归档
today = datetime.date.today()
select = {'day': connection.ops.date_trunc_sql('day', 'create_time')}
deploy_date_count = Task.objects.filter(
 create_time__range=(today - datetime.timedelta(days=7), today)
).extra(select=select).values('day').annotate(number=Count('id'))

Q 的使用

Q对象可以对关键字参数进行封装,从而更好的应用多个查询,可以组合&(and)、|(or)、~(not)操作符。

例如下边的语句

from django.db.models import Q

User.objects.filter(
 Q(role__startswith='sre_'),
 Q(name='公众号') | Q(name='运维咖啡吧')
)

转换成SQL语句如下:

select * from User where role like 'sre_%' and (name='公众号' or name='运维咖啡吧')

通常更多的时候我们用Q来做搜索逻辑,比如前台搜索框输入一个字符,后台去数据库中检索标题或内容中是否包含

_s = request.GET.get('search')

_t = Blog.objects.all()
if _s:
 _t = _t.filter(
 Q(title__icontains=_s) |
 Q(content__icontains=_s)
 )

return _t

外键:ForeignKey

表结构:

class Role(models.Model):
 name = models.CharField(max_length=16, unique=True)


class User(models.Model):
 username = models.EmailField(max_length=255, unique=True)
 role = models.ForeignKey(Role, on_delete=models.CASCADE)

正向查询:

# 查询用户的角色名
_t = User.objects.get(username='运维咖啡吧')
_t.role.name

反向查询:

# 查询角色下包含的所有用户
_t = Role.objects.get(name='Role03')
_t.user_set.all()

另一种反向查询的方法:

_t = Role.objects.get(name='Role03')

# 这种方法比上一种_set的方法查询速度要快
User.objects.filter(role=_t)

第三种反向查询的方法:

如果外键字段有related_name属性,例如models如下:

class User(models.Model):
 username = models.EmailField(max_length=255, unique=True)
 role = models.ForeignKey(Role, on_delete=models.CASCADE,related_name='roleUsers')

那么可以直接用related_name属性取到某角色的所有用户

_t = Role.objects.get(name = 'Role03')
_t.roleUsers.all()

M2M:ManyToManyField

表结构:

class Group(models.Model):
name = models.CharField(max_length=16, unique=True)

class User(models.Model):
username = models.CharField(max_length=255, unique=True)
groups = models.ManyToManyField(Group, related_name='groupUsers')

正向查询:

# 查询用户隶属组
_t = User.objects.get(username = '运维咖啡吧')
_t.groups.all()

反向查询:

# 查询组包含用户
_t = Group.objects.get(name = 'groupC')
_t.user_set.all()

同样M2M字段如果有related_name属性,那么可以直接用下边的方式反查

_t = Group.objects.get(name = 'groupC')
_t.groupUsers.all()

get_object_or_404

正常如果我们要去数据库里搜索某一条数据时,通常使用下边的方法:

_t = User.objects.get(id=734)

但当id=724的数据不存在时,程序将会抛出一个错误

abcer.models.DoesNotExist: User matching query does not exist.

为了程序兼容和异常判断,我们可以使用下边两种方式:

方式一:get改为filter

_t = User.objects.filter(id=724)
# 取出_t之后再去判断_t是否存在

方式二:使用get_object_or_404

from django.shortcuts import get_object_or_404

_t = get_object_or_404(User, id=724)
# get_object_or_404方法,它会先调用django的get方法,如果查询的对象不存在的话,则抛出一个Http404的异常

实现方法类似于下边这样:

from django.http import Http404

try:
 _t = User.objects.get(id=724)
except User.DoesNotExist:
 raise Http404
get_or_create

顾名思义,查找一个对象如果不存在则创建,如下:

object, created = User.objects.get_or_create(username='运维咖啡吧')

返回一个由object和created组成的元组,其中object就是一个查询到的或者是被创建的对象,created是一个表示是否创建了新对象的布尔值

实现方式类似于下边这样:

try:
 object = User.objects.get(username='运维咖啡吧')
 created = False
exception User.DoesNoExist:
 object = User(username='运维咖啡吧')
 object.save()

 created = True

returen object, created

执行原生SQL

Django中能用ORM的就用它ORM吧,不建议执行原生SQL,可能会有一些安全问题,如果实在是SQL太复杂ORM实现不了,那就看看下边执行原生SQL的方法,跟直接使用pymysql基本一致了

from django.db import connection

with connection.cursor() as cursor:
 cursor.execute('select * from accounts_User')
 row = cursor.fetchall()

return row

注意这里表名字要用app名+下划线+model名的方式

Django model select的多种用法详解

Python 相关文章推荐
Python优化技巧之利用ctypes提高执行速度
Sep 11 Python
Python实现向服务器请求压缩数据及解压缩数据的方法示例
Jun 09 Python
python 请求服务器的实现代码(http请求和https请求)
May 25 Python
对python中的 os.mkdir和os.mkdirs详解
Oct 16 Python
python引用(import)某个模块提示没找到对应模块的解决方法
Jan 19 Python
Python实现统计英文文章词频的方法分析
Jan 28 Python
关于Python作用域自学总结
Jun 10 Python
python脚本调用iftop 统计业务应用流量的思路详解
Oct 11 Python
python实现身份证实名认证的方法实例
Nov 08 Python
pytorch SENet实现案例
Jun 24 Python
python连接mysql有哪些方法
Jun 24 Python
python实现三壶谜题的示例详解
Nov 02 Python
python删除文件夹下相同文件和无法打开的图片
Jul 16 #Python
Python split() 函数拆分字符串将字符串转化为列的方法
Jul 16 #Python
python实现字符串完美拆分split()的方法
Jul 16 #Python
python如何删除文件中重复的字段
Jul 16 #Python
python字符串切割:str.split()与re.split()的对比分析
Jul 16 #Python
Python使用正则表达式分割字符串的实现方法
Jul 16 #Python
Python Django切换MySQL数据库实例详解
Jul 16 #Python
You might like
PHP脚本数据库功能详解(中)
2006/10/09 PHP
使用TinyButStrong模板引擎来做WEB开发
2007/03/16 PHP
PHP的PDO错误与错误处理
2019/01/27 PHP
PHP命名空间与自动加载机制的基础介绍
2019/08/25 PHP
JavaScript高级程序设计 阅读笔记(十八) js跨平台的事件
2012/08/14 Javascript
jquery获取radio值实例
2014/10/16 Javascript
浅谈javascript中的闭包
2015/05/13 Javascript
JavaScript中使用concat()方法拼接字符串的教程
2015/06/06 Javascript
JavaScript中Function函数与Object对象的关系
2015/12/17 Javascript
仅一个form表单 js实现注册信息依次填写提交功能
2016/06/12 Javascript
AngularJS使用ng-app自动加载bootstrap框架问题分析
2017/01/04 Javascript
使用snowfall.jquery.js实现爱心满屏飞的效果
2017/01/05 Javascript
基于JS实现仿京东搜索栏随滑动透明度渐变效果
2017/07/10 Javascript
ajax+node+request爬取网络图片的实例(宅男福利)
2017/08/28 Javascript
node.js遍历目录的方法示例
2018/08/01 Javascript
JavaScript中变量、指针和引用功能与操作示例
2018/08/04 Javascript
浅谈VUE防抖与节流的最佳解决方案(函数式组件)
2019/05/22 Javascript
vue3中轻松实现switch功能组件的全过程
2021/01/07 Vue.js
[01:13]DOTA2群星解读国服召集令 一起说出回归的理由
2013/07/17 DOTA
Python中http请求方法库汇总
2016/01/06 Python
Django开发中复选框用法示例
2018/03/20 Python
Python爬虫包BeautifulSoup实例(三)
2018/06/17 Python
Python3安装Pillow与PIL的方法
2019/04/03 Python
Python闭包与装饰器原理及实例解析
2020/04/30 Python
详解pandas获取Dataframe元素值的几种方法
2020/06/14 Python
Python3读写ini配置文件的示例
2020/11/06 Python
Python之多进程与多线程的使用
2021/02/23 Python
伦敦最有品味的百货:Liberty London
2016/11/12 全球购物
特罗佩亚包官方网站:Tropea
2017/01/03 全球购物
yy婚礼主持词
2014/03/14 职场文书
公务员保密承诺书
2014/03/27 职场文书
大学生通用个人自我评价
2014/04/27 职场文书
体育专业自荐书
2014/05/29 职场文书
2014年应急管理工作总结
2014/11/26 职场文书
对外汉语教师推荐信
2015/03/27 职场文书
启迪人心的励志语录:脾气永远不要大于本事
2020/01/02 职场文书