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 捕获shell脚本的输出结果实例
Jan 04 Python
pygame加载中文名mp3文件出现error
Mar 31 Python
python实现协同过滤推荐算法完整代码示例
Dec 15 Python
TensorFlow实现Softmax回归模型
Mar 09 Python
python实现录音小程序
Oct 26 Python
Python实现分段线性插值
Dec 17 Python
Python适配器模式代码实现解析
Aug 02 Python
Python统计分析模块statistics用法示例
Sep 06 Python
Python安装与卸载流程详细步骤(图解)
Feb 20 Python
python中round函数保留两位小数的方法
Dec 04 Python
查找适用于matplotlib的中文字体名称与实际文件名对应关系的方法
Jan 05 Python
Python面向对象编程之类的概念
Nov 01 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/12/25 PHP
php横向重复区域显示二法
2008/09/25 PHP
PHP文章按日期(月日)SQL归档语句
2012/11/29 PHP
php简单实现发送带附件的邮件
2015/06/10 PHP
php随机获取金山词霸每日一句的方法
2015/07/09 PHP
WordPress开发中短代码的实现及相关函数使用技巧
2016/01/05 PHP
PHP-X系列教程之内置函数的使用示例
2017/10/16 PHP
浅析PHP中json_encode与json_decode的区别
2020/07/15 PHP
js 获取Listbox选择的值的代码
2010/04/15 Javascript
js面向对象设计用{}好还是function(){}好(构造函数)
2011/10/23 Javascript
Firefox中通过JavaScript复制数据到剪贴板(Copy to Clipboard 跨浏览器版)
2013/11/22 Javascript
angularJS 中$attrs方法使用指南
2015/02/09 Javascript
AngularJS延迟加载html template
2016/07/27 Javascript
实现div滚动条默认最底部以及默认最右边的示例代码
2017/11/15 Javascript
jquery层次选择器的介绍
2019/01/18 jQuery
微信小程序实现抖音播放效果的实例代码
2020/04/11 Javascript
JavaScript实现瀑布流布局的3种方式
2020/12/27 Javascript
[01:56]林书豪DOTA2上海特级锦标赛励志短片
2016/03/05 DOTA
[58:23]LGD vs TNC 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
python写的一个文本编辑器
2014/01/23 Python
教你用Python脚本快速为iOS10生成图标和截屏
2016/09/22 Python
一些常用的Python爬虫技巧汇总
2016/09/28 Python
Python的地形三维可视化Matplotlib和gdal使用实例
2017/12/09 Python
Python设计模式之观察者模式原理与用法详解
2019/01/16 Python
python调用摄像头拍摄数据集
2019/06/01 Python
非凡女性奢华谦虚风格:The Modist
2017/10/28 全球购物
意大利运动服减价商店:ScontoSport
2020/03/10 全球购物
高中地理教学反思
2014/01/29 职场文书
2014全国两会心得体会
2014/03/17 职场文书
森林病虫害防治方案
2014/06/02 职场文书
群众对十八届四中全会的期盼
2014/10/17 职场文书
Python jiaba库的使用详解
2021/11/23 Python
Vue提供的三种调试方式你知道吗
2022/01/18 Vue.js
一次Mysql update sql不当引起的生产故障记录
2022/04/01 MySQL
阿里云日志过滤器配置日志服务
2022/04/09 Servers
MySQL新手入门进阶语句汇总
2022/09/23 MySQL