zoukankan      html  css  js  c++  java
  • 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)
    

     

  • 相关阅读:
    一步一步学习sharepoint2010 workflow 系列第二部分:sharepoint无代码工作流 第3章 自定义工作流(Custom Designer workflows)
    巧用BroadcastReceiver实现开机“自”启动
    webview 与 javascript
    android webview设置内容的字体大小
    android中使用BitmapFactory的decodeStream()方法解码图片失败问题
    在ListView的item项里使用CheckBox或者Button时,OnItemClickListener无响应的问题
    修改Android中strings.xml文件, 动态改变数据
    在使用google map 时出现Android关于java.lang.NoClassDefFoundError问题
    android中String.xml可以传参数的资源
    android 代码实现应用强制装到手机内存
  • 原文地址:https://www.cnblogs.com/huidou/p/10757852.html
Copyright © 2011-2022 走看看