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)