django orm 基本操作

本文详细介绍Django ORM的基本操作,包括数据查询、过滤、排序、聚合及多对多关系处理,涵盖ORM语法、日期操作、复杂查询及字段比较器F的使用。

django官网查询集

QuerySet对象转换成字典对象

from django.forms.models import model_to_dict  
u = User.objects.get(id=1) 
u_dict = model_to_dict(u)
type(u_dict) 

QuerySet字段imageTag中的值直接存成列表

xx.objects.filter(imageService=imageService).values_list('imageTag', flat=True)

ORM大于等于小于符号

__gt 大于
__gte 大于等于
__lt 小于
__lte 小于等于

ORM常用操作

# 获取数据,不存在则创建,返回元组,若创建成功则第二个字段返回True(<Zzdtest 1>, False)
az_dict = {"az_name": zone_name}
AZ.objects.get_or_create(**az_dict)
# 查询所有结果
music = Music.objects.all()
print('music:', music)
# 过滤条件,可以在后面接 .count() 统计过滤的数据
fi = Music.objects.filter(music_name='忘不了')
print('filter: ',fi)
# 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
ge = Music.objects.get(music_name='忘不了')
print('get: ',ge)
# 筛选条件不匹配的对象
ex = Music.objects.exclude(music_name='忘不了')
print('exclude: ', ex)
# 返回可迭代的字典序列
va = Music.objects.values()
print('values: ', va)
# 返回的是一个元组序列
vals = Music.objects.values_list()
print('values_list: ', vals)
# 对查询结果排序
order = Music.objects.order_by()
print('order: ', order)
# 对查询结果反向排序
reverse = Music.objects.reverse()
print('reverse', reverse)
# 返回数据库中匹配查询(QuerySet)的对象数量
count = Music.objects.count()
print('count:', count)
# 返回第一条记录
first = Music.objects.first()
print('first: ',first)
# 返回最后一条记录
last = Music.objects.last()
print('last: ',last)
# 如果QuerySet包含数据,就返回True,否则返回False
exi = Music.objects.exists()
print('exists: ',exi)
distinct = Music.objects.distinct()
print('distinct: ', distinct)
# 删除数据
Music.objects.first(name='zhangsan').delete()
# 更新数据
Music.objects.first(name='zhangsan').update(age=18)

ORM双下划线操作

# 获取id大于4 且 小于6的值
ltgt = Music.objects.filter(id__lt=6, id__gt=4)
print('ltgt: ', ltgt)
# 获取id等于36的数据
ideq = Music.objects.filter(id__in=[3,6])
print('ideq: ', ideq)
# 获取id不等于36的数据
notin = Music.objects.exclude(id__in=[3, 6])
print('notin: ', notin)
# 获取music_name字段包含"祝"的
contains = Music.objects.filter(music_name__contains='祝')
print('contains: ', contains)
# icontains大小写不敏感
icontains = Music.objects.filter(music_author__icontains='s')
print('icontains: ', icontains)
# id范围是15的,等价于SQL的bettwen and
id__range = Music.objects.filter(id__range=[1,5])
print('id__range: ', id__range)

输出:

music: <QuerySet [<Music: Music object (3)>, <Music: Music object (4)>, <Music: Music object (5)>, <Music: Music object (6)>]>
filter:  <QuerySet [<Music: Music object (5)>]>
get:  Music object (5)
exclude:  <QuerySet [<Music: Music object (3)>, <Music: Music object (4)>, <Music: Music object (6)>]>
values:  <QuerySet [{'id': 3, 'music_author': '张学友', 'music_name': '祝福', 'music_album': '祝福', 'music_time': '1997年1月', 'music_type': '流行', 'music_lyrics': '张学友', 'music_arranger': '张
学友'}, {'id': 4, 'music_author': '张学友sssssS', 'music_name': '祝福', 'music_album': '祝福', 'music_time': '1997年1月', 'music_type': None, 'music_lyrics': '', 'music_arranger': '张学友'}, {'id':
5, 'music_author': '张学友', 'music_name': '忘不了', 'music_album': '忘不了', 'music_time': '1997年1月', 'music_type': '流行', 'music_lyrics': '张学友', 'music_arranger': '张学友'}, {'id': 6, 'music
_author': '张学友', 'music_name': '爱你', 'music_album': '吻别22222', 'music_time': '1997年1月', 'music_type': '流行', 'music_lyrics': '张学友', 'music_arranger': '张学友'}]>
values_list:  <QuerySet [(3, '张学友', '祝福', '祝福', '1997年1月', '流行', '张学友', '张学友'), (4, '张学友sssssS', '祝福', '祝福', '1997年1月', None, '', '张学友'), (5, '张学友', '忘不了', '忘不了
', '1997年1月', '流行', '张学友', '张学友'), (6, '张学友', '爱你', '吻别22222', '1997年1月', '流行', '张学友', '张学友')]>
order:  <QuerySet [<Music: Music object (3)>, <Music: Music object (4)>, <Music: Music object (5)>, <Music: Music object (6)>]>
reverse <QuerySet [<Music: Music object (3)>, <Music: Music object (4)>, <Music: Music object (5)>, <Music: Music object (6)>]>
count: 4
first:  Music object (3)
last:  Music object (6)
exists:  True
distinct:  <QuerySet [<Music: Music object (3)>, <Music: Music object (4)>, <Music: Music object (5)>, <Music: Music object (6)>]>
ltgt:  <QuerySet [<Music: Music object (5)>]>
ideq:  <QuerySet [<Music: Music object (3)>, <Music: Music object (6)>]>
notin:  <QuerySet [<Music: Music object (4)>, <Music: Music object (5)>]>
contains:  <QuerySet [<Music: Music object (3)>, <Music: Music object (4)>]>
icontains:  <QuerySet [<Music: Music object (4)>]>
id__range:  <QuerySet [<Music: Music object (3)>, <Music: Music object (4)>, <Music: Music object (5)>]>

ORM日期操作

# 定义表
class User(models.Model):
    id = models.BigAutoField(primary_key=True)
    # 创建时间
    create_datetime = models.DateTimeField(auto_now_add=True)
    # 最后修改时间
    modify_datetime = models.DateTimeField(auto_now=True)

# 查询
date_time = time.strftime("%Y-%m-%d", time.localtime())
res = User.objects.filter(create_datetime__startswith=date_time)

# 查询某一个字段的数据
# create_datetime是models中的字段名
list_raw = User.objects.filter(name='xxx') \
    .extra(select={"create_datetime": "DATE_FORMAT(create_datetime, '%%Y-%%m-%%d %%H:%%i:%%s')"}) \
    .values('id', 'create_datetime').order_by('-create_datetime')

model案例

class Organization(models.Model):
    organization_type_choices = (("company", "公司"), ("department", "部门"))
    name = models.CharField(max_length=60, verbose_name="名称")
    type = models.CharField(max_length=20, choices=organization_type_choices, default="company", verbose_name="类型")
    pid = models.ForeignKey("self", null=True, blank=True, on_delete=models.SET_NULL, verbose_name="父类组织")
    
class User(models.Model):
    id = models.BigAutoField(primary_key=True)
    department = models.ForeignKey("Organization", null=True, blank=True, on_delete=models.SET_NULL, verbose_name="部门")
    roles = models.ManyToManyField(Role)

class Role(models.Model):
    name = models.CharField(max_length=32, unique=True, verbose_name="角色")
    permissions = models.ManyToManyField("Permission", blank=True, verbose_name="权限")
    desc = models.CharField(max_length=50, blank=True, null=True, verbose_name="描述")

ORM外键ForeignKey查询

正向查找
语法:对象.关联字段.字段

# 首先过滤name
user = User.objects.filter(name=name).first()
# 再根据用户查询外键关联的字段name(根据用户查询部门)
department = user.department.name
# 根据部门查询该部门用户
User.objects.filter(department__name='后端研发组')

反向查找(通过过外键表获取主表的信息)

# 返回列表
org = Organization.objects.filter(id=user.department_id).select_related()

ORM外键ForeignKey新增

models
class Project(models.Model):
    id = models.AutoField(primary_key=True)
    project = models.CharField(max_length=128, null=True, help_text='项目名称')
    ... ...
    
class ProjectApplication(models.Model):
    ... ...
    id = models.AutoField(primary_key=True)
    projects = models.ForeignKey("Project", null=True, blank=True, on_delete=models.SET_NULL, verbose_name="项目")
    ... ...

# 先获取对象信息
project_exist = Project.objects.filter(project=project).first()
# 外建projects直接赋值这个对象即可
ProjectApplication.objects.create(project=project, env=env,
                                                      compile_cmd=compile_cmd, domain=domain, projects=project_exist)

ORM多对多ManyToManyField查询一(优先)

正向查询–根据用户名查角色

# 多对多正向查询--根据用户名查角色
user = User.objects.filter(name=name).first()
role = user.roles.all().values('name')

反向查询–根据角色查询所有用户

# 多对多反向查询--根据角色查询所有用户
roles = Role.objects.get(name='普通用户')
users = roles.user_set.all().values('name')


ORM多对多ManyToManyField查询二(较少)

另外一种方法可也以,在不确定条件的情况下可以遍历所有,再根据条件判断,效率较低,用的较少。
正向查询

# 
>>> from rbac.models import *
>>> User.objects.all()
<QuerySet [<User: zzd>, <User: scm>, <User: test>, <User: dev>, <User: master>, <User: config>, <User: dev2>]>
>>> User.objects.all()[0]
<User: zzd>
>>> User.objects.all()[0].email
'zhangzd@olafuwu.com'
>>> User.objects.all()[0].roles.all()
<QuerySet [<Role: 系统管理员>, <Role: 运维群>]>
>>> User.objects.all()[0].roles.all()[0].name
'系统管理员'

反向查询

>>> Role.objects.all()[1]
<Role: 普通用户>
>>> Role.objects.all()[1].name
'普通用户'
>>> Role.objects.all()[1].user_set.all()
<QuerySet [<User: scm>, <User: test>, <User: dev>, <User: master>, <User: config>, <User: dev2>]>
>>> Role.objects.all()[1].user_set.all()[0]
<User: scm>
>>> Role.objects.all()[1].user_set.all()[0].name
'scm'

ORM多对多ManyToManyField增/改/删

# 我这里User表中的字段roles与Role是多对多关系,思路是取出user数据,再直接通过.roles.add()即可
>>> user = User.objects.filter(name='zzd').first()
>>> user
<User: zzd>
>>> user.roles.add(3) # 添加到id为3的role中
>>> user.roles.add(3,4) # 同时添加到id为3,4的role中

改,注意是列表
>>> user.roles.set([3]) # 只留3这个id关系

删
>>> user.roles.remove(4)  # 删除4
>>> user.roles.clear() # 清空所有关系

复杂查询

竞争条件(race condition)

两个线程同时获取一个Comment对象,第一个线程对它的up字段值加1并保存,这不会有问题。之后,第二个线程也对up字段值加1并保存,那么第一个线程的工作就丢失了。为了避免这种情况发生,最好的办法是让数据库负责更新过程,使用F对象可以提供这种能力。

# 不使用F对象这样操作会导致第二个线程数据不一致
>>> comment = Comment.objects.get(id=1)
>>> comment.up += 1
>>> comment.save()

# 使用F对象更新值可以避免race condition情况
>>> comment = Comment.objects.get(id=1)
>>> comment.up
1
>>> comment.up = F('up') + 1
>>> comment.save()

多字段查询过滤器Q

用于复杂查询,把关键字参数封装到一起,并传递给filter、exclude、get等查询方法。可以使用&、| 运算符组合,使用~取反。

# 查询project字段或message字段包含关键字
condition = Q(project__icontains=search_words) | Q(message__icontains=search_words)
WorkOrder.objects.filter(condition).order_by('id')
# 多条件查询嵌套
condition = Q(Q(name__icontains=search_words) & Q(expire_day__lte=filter_words)) | Q(
                    Q(ip__icontains=search_words) & Q(expire_day__lte=filter_words))

过滤+排除案例(通过传递同时使用filter+exclude)

condition = Q(next_user__contains=username) & Q(
                        step_start__lt=F('step_finish'))
condition2 = Q(approval_refuse__in=['1']) | Q(approval_revocation__in=['1']) | Q(
                        step_start__gte=F('step_finish'))
work_order = WorkOrder.objects.filter(condition).exclude(condition2).order_by('-id')

字段查询比较器F

用于操作数据库中某一列的值,它可以在没有实际访问数据库获取数据值的情况下对字段的值进行应用。支持对F对象引用的字段使用加减乘除等算数操作。

from django.db.models import F
# 查询数据,取出step_start字段 大于等于 step_finish字段的数据
WorkOrder.objects.filter(step_start__gte=F('step_finish')).order_by('id')

# 查询up中数值小于down中数值的数据
Comment.objects.filter(up__lte=F('down'))
<QuerySet [<Comment: 2: hhhhh>, <Comment: 1: gagaga>]>

# 查询up中数值小于down中数值 2倍 的数据
Comment.objects.filter(up__lte=F('down') * 2)
<QuerySet [<Comment: 2: hhhhh>, <Comment: 1: gagaga>]>


聚合查询

from django.db.models import Max, Min, Sum, Avg, Count
# 查询字段的平均数、总和、最大值
WorkOrder.objects.all().aggregate(Avg("step_finish"),Sum("step_finish"), Max("step_finish"))

分组查询

# 通过Organization对user表进行分组计数
Organization.objects.annotate(count=Count("user")).values("name", "count")
# 通过Organization对user表中的mobile平均数计算测试
Organization.objects.annotate(avg=Avg("user__mobile")).values("name", "avg")

参考文献:
https://www.cnblogs.com/study-learning/p/9969486.html
https://docs.djangoproject.com/en/2.2/ref/models/querysets/
https://blog.csdn.net/qq_34755081/article/details/82779489

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值