Django ORM

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)

 

原文地址:https://www.cnblogs.com/huidou/p/10757852.html