django 操作数据库

本贴最后更新于 1700 天前,其中的信息可能已经时移世异

转载 自:https://blog.csdn.net/u012762054/article/details/81660619?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-taskhttps://blog.csdn.net/u012762054/article/details/81660619?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

基本操作

# 获取所有数据,对应SQL:select * from UserUser.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 = 724User.objects.get(id=123)

常用操作

# 获取总数,对应SQL:select count(1) from UserUser.objects.count() # 获取总数,对应SQL:select count(1) from User where name = '运维咖啡吧'User.objects.filter(name='运维咖啡吧').count() # 大于,>,对应SQL:select * from User where id > 724User.objects.filter(id__gt=724) # 大于等于,>=,对应SQL:select * from User where id >= 724User.objects.filter(id__gte=724) # 小于,<,对应SQL:select * from User where id < 724User.objects.filter(id__lt=724) # 小于等于,<=,对应SQL:select * from User where id <= 724User.objects.filter(id__lte=724) # 同时大于和小于, 1 < id < 10,对应SQL:select * from User where id > 1 and id < 10User.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 nullUser.objects.filter(pub_date__isnull=True) # 不为空:isnull=False,对应SQL:select * from User where pub_date is not nullUser.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 8User.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 idUser.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 descUser.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 CountUser.objects.values_list('username').annotate(Count('id')) # 去重distinct,对应SQL:select distinct(username) from UserUser.objects.values('username').distinct().count() # filter多列、查询多列,对应SQL:select username,fullname from accounts_userUser.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’))

时间字段

# 匹配日期,dateUser.objects.filter(create_time__date=datetime.date(2018, 8, 1))User.objects.filter(create_time__date__gt=datetime.date(2018, 8, 2)) # 匹配年,yearUser.objects.filter(create_time__year=2018)User.objects.filter(create_time__year__gte=2018) # 匹配月,monthUser.objects.filter(create_time__month__gt=7)User.objects.filter(create_time__month__gte=7) # 匹配日,dayUser.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) # 匹配时,hourUser.objects.filter(create_time__hour=9)User.objects.filter(create_time__hour__gte=9) # 匹配分,minuteUser.objects.filter(create_time__minute=15)User.objects.filter(create_time__minute_gt=15) # 匹配秒,secondUser.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='运维咖啡吧')
 * from User where role like 'sre_%' and (name='公众号' or name='运维咖啡吧')
from User where role like 'sre_%' and (name='公众号' or name='运维咖啡吧')
 User where role like 'sre_%' and (name='公众号' or name='运维咖啡吧')
User where role like 'sre_%' and (name='公众号' or name='运维咖啡吧')
 where role like 'sre_%' and (name='公众号' or name='运维咖啡吧')
where role like 'sre_%' and (name='公众号' or name='运维咖啡吧')
 role like 'sre_%' and (name='公众号' or name='运维咖啡吧')
role like 'sre_%' and (name='公众号' or name='运维咖啡吧')
 like 'sre_%' and (name='公众号' or name='运维咖啡吧')
like 'sre_%' and (name='公众号' or name='运维咖啡吧')
 'sre_%' and (name='公众号' or name='运维咖啡吧')
'sre_%' and (name='公众号' or name='运维咖啡吧')
 and (name='公众号' or name='运维咖啡吧')
and (name='公众号' or name='运维咖啡吧')
 (name='公众号' or name='运维咖啡吧')
name='公众号' or name='运维咖啡吧')
='公众号' or name='运维咖啡吧')
'公众号' or name='运维咖啡吧')
 or name='运维咖啡吧')
or name='运维咖啡吧')
 name='运维咖啡吧')
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)
get(id=734)
(id=734)
734)
)

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

abcer.models.DoesNotExist: User matching query does not exist.
.models.DoesNotExist: User matching query does not exist.
.DoesNotExist: User matching query does not exist.
: User matching query does not exist.
User matching query does not exist.
 matching query does not exist.
matching query does not exist.
 query does not exist.
query does not exist.
 does not exist.
does not exist.
 not exist.
not exist.
 exist.
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='运维咖啡吧')
, created = User.objects.get_or_create(username='运维咖啡吧')
'运维咖啡吧')
)

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

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

try:    object = User.objects.get(username='运维咖啡吧')     created = Falseexception 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
  • Django
    47 引用 • 72 回帖 • 4 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    543 引用 • 672 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...