Django ORM 一对多,多对多关系 的增删改查
ORM一对多,多对多关系
用到一对多,也可以应用到多对多
一对多的增删改查
跨表的话需要双下划线去跨字段 sch__name
一对多的查询
_class = 'abc'
obj = models.Class.objects.all() # --> [queryset,queryset]
obj1 = models.Class.objects.filter(name=_class) # queryset
for i in obj:
print (i.name, i.sch.name) # 跨表查询
obj2 = models.Class.objects.filter(name=_class).first()
print (obj2.name, obj2.sch.name)
for i in obj.user.all():
print (i.name, i.username) #跨表查询,将里面的所有用户全部打印出来
一对多创建
创建
obj= models.School.ojbect.filter(name='aaa_ban')
#先创建了 学校的班级
class_obj = models.Class.ojbect.create(name='aaa',sch=ojb)
#然后再使用这个班级去创建新的用户
print (class_obj.sch.name) #通过 sch 跨表,点出来创建新学校的名字
删除
obj = models.Class.objects.filter(name='aaa_ban').delete()
# 选择相应的名字字段,然后删除
修改
models.Class.objects.filter(sch__name='aaa_ban').update(name='10_python')
# 跨表字段 需要加双下划线 sch__name
#更新的是Class 中的 name字段信息。更新成 '10_python'
删除
models.Class.objects.filter(sch__name='10_python').delete()
# 跨表字段删除,在class里面的10_python ,全部删除
多对多的操作
正向跨表去操作数据
class 这个数据表里有这个 user 字段,用了他的一对多关系,通过这个user字段拿到它的所有数据,这里的所有数据就是UserInfo里的数据。
这样就可以实现正向跨到另一张 UserInfo 表里去。
查看
ojb = models.Class.objects.filter(name='aaa').first()
#因为是一对多关系,所以拿到了可能是多个数据
for i in ojb.user.all()
# 用了他的一对多关系,通过他的user字段里的拿到它的所有数据,就可以这个数据全部循环出来
print (i.name, i.username) #这里是的 UserInfo 的user数据
增 删 改add()
#增加remove()
#删除表 ,只删一条数据clear()
#清空表 , 把所有关系的表全部清空
修改需要通过以上的方法协同使用达到目标
第一种,使用创建UserInfo的用户信息的ID再来添加多对多关系的增加
使用创建的时候的ID然后再加入多对多的关系里去
obj_c = models.Class.objects.filter(name='aaa').first()
user_obj = models.Class.objects.create(name='test_many',username='test_to_test')
#先创建这个用户信息,再使用它的ID添加多对多关系里去
user_obj.id # 就是这个对象ID了
obj_c.user.add(user_obj.id)
#这里的 .user 很重要,他是跨表的关键 。
#add(默认是数字),是增加关系的字段的ID。但不止是数字
第二种 使用现有的用户信息,根据filter查询找到他的ID再进行添加多对多关系
obj_c = models.Class.objects.filter(name='aaa').first() #第一次查找 的条件
user_obj = models.UserInfo.objects.filter(name='abc') #第二次查找 的条件
obj_c.user.add(*user_obj) # 针对第三张表去增加。 要是用这个user_obj 对象 需要增加*
删除
和增加类似 ,只需要把add() 换成remove 即可
obj_c = models.Class.objects.filter(name='aaa').first() #第一次查找 的条件
user_obj = models.UserInfo.objects.filter(name='abc') #第二次查找 的条件
obj_c.user.remove(*user_obj) # 针对第三章表去删除。 要是用这个user_obj 对象 需要增加*
many to many 多对多关系 删除 -- clear 清空多对多关系表和对应关系的数据
obj_s = models.Class.objects.filter(name='bbb_ban').first()
# 针对多对多关系,将这个字段的内容的所有多对多关系全部清空。
user_obj = models.UserInfo.objects.filter(name='baba')
obj_s.user.clear()
修改
先 clear 后 add
obj_c = models.Class.objects.filter(name='aaa').first() #第一次查找的条件。针对多对多关系,将这个字段的内容的所有多对多关系
全部清空。
user_obj = models.UserInfo.objects.filter(name='abc') #第二次查找的条件。只要有一个符合多对多关系的条件就行
obj_c.user.clear() # 针对第三章表去增加。 要是用这个user_obj 对象 需要增加*
obj_c.user.add(*user_obj) # 先清空再添加关系!
反向跨表操作
已知的表去跨表,根据类的名字的小写去找到所需的字段
反向查询
user_obj = models.UserInfo.objects.filter(name='abc').first() # 先把UserInfo的条件写出查询来
for i in user_obj.class_set.all():
print (i.name)
# user_obj 通过这个表的类的名字的小写 ,点出来类的名字的小写 .class_set.all() 拿到里面所有的数据
# 如果数据库里加了 related_name='clauser' 就可以不用set了,直接 user_obj.clauser.all() 也可以实现
# related_name : 关联对象反向引用描述符。
反向 增加
user_obj = models.UserInfo.objects.filter(name='abc').first()
#先通过已知的UserInfo表里的字段,查询得到对象
obj_c = models.Class.objects.filter(name='bbb') #再 查询一个班级的
user_obj.class_set.add(*obj_c)
# 把这两个查询的结果添加进 多对多的关系表里。这里可以写 obj_c.id 或者 *obj_c
反向删除 -- remove
user_obj = models.UserInfo.objects.filter(name='abc').first()
#先通过已知的UserInfo表里的字段,查询得到对象
obj_c = models.Class.objects.filter(name='bbb') #再 查询一个班级的
user_obj.class_set.remove(*obj_c)
# 把这两个查询的结果添加进 多对多的关系表里。这里可以写 obj_c.id 或者 *obj_c
反向删除 -- clear
user_obj = models.UserInfo.objects.filter(name='abc').first()
#先通过已知的UserInfo表里的字段,查询得到对象
obj_c = models.Class.objects.filter(name='bbb') #再 查询一个班级的
user_obj.class_set.clear()
# 把这两个查询的结果添加进 多对多的关系表里。这里可以写 obj_c.id 或者 *obj_c
Django 条件查询
ORM高级—双下划线 条件查询
双下划线(__)之单表条件查询
models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值
models.Tb1.objects.filter(id__in=[11, 22, 33])
# 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33])
# 匹配ID 在列表中的值 或者可以是 not in #filter的反序 exclude,即取反
models.Tb1.objects.filter(name__contains="ven") #查询包含的关键字
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and
startswith,istartswith, endswith, iendswith,
istartswith #查询以什么开头
endswith #查询以什么结尾的
惰性机制(迭代/切片) F查询和Q查询
obj = models.UserInfo.all() #queryset
for i in obj[1:3]: #切片
print (i.name)
F 查询
from django.db.models import F
models.UserInfo.objects.update(password=F('password')+1000) #对这个字段的数字加1000,如果不是int则会跳过
Q 查询
from django.db.models improt Q
obj = models.UserInfo.objects.filter(Q(username__startswith='t')|Q(username__endswith='c')) #或的关系
obj = models.UserInfo.objects.filter(Q(username__startswith='t'),Q(username__endswith='c')) #与的关系
obj = models.UserInfo.objects.filter(Q(username='xxx') | Q(password='xxx')) # 或的关系
for i in obj:
print (i.name)
# F 使用查询条件的值,专门取对象中某列值的操作
# from django.db.models import F
# models.Tb1.objects.update(num=F('num')+1)
# Q 构建搜索条件
from django.db.models import Q
#1 Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询
q1=models.Book.objects.filter(Q(title__startswith='P')).all()
print(q1)#[<Book: Python>, <Book: Perl>]
# 2、可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象。
Q(title__startswith='P') | Q(title__startswith='J')
# 3、Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合
Q(title__startswith='P') | ~Q(pub_date__year=2005)
# 4、应用范围:
# Each lookup function that takes keyword-arguments (e.g. filter(),
# exclude(), get()) can also be passed one or more Q objects as
# positional (not-named) arguments. If you provide multiple Q object
# arguments to a lookup function, the arguments will be “AND”ed
# together. For example:
Book.objects.get(
Q(title__startswith='P'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
#sql:
# SELECT * from polls WHERE question LIKE 'P%'
# AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
# import datetime
# e=datetime.date(2005,5,6) #2005-05-06
5、Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。
正确:
Book.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),title__startswith='P')
错误:
Book.objects.get(
question__startswith='P',Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
反向查找的related_name
使用related_name='自定义名'
,反向查找的时候不用再用 _set 来反向查找
#没使用 related_name='自定义名'
obj_s = models.UserInfo.objects.filter(name='aaa').first()
for i in obj_s.class_set.all():
print (i.name)
#没使用 related_name='clauser'
obj_s = models.UserInfo.objects.filter(name='aaa').first()
for i in obj_s.clauser.all():
print (i.name)