zoukankan      html  css  js  c++  java
  • Django之model联表:一对多、跨表操作,联表查询

    表结构概述

    model.py :

    class Something(models.Model):
        name = models.CharField(max_length=32)
    
    
    class UserType(models.Model):
        caption = models.CharField(max_length=32)
        s = models.ForeignKey('Something')
      #这个s不是字段名,字段名是something_id,这里的s作用是查询的时候用:row.s.id或row.s.name
    
    
    # 超级管理员,普通用户,游客,黑河
    class UserInfo(models.Model):
        user = models.CharField(max_length=32)
        pwd = models.CharField(max_length=32)
        user_type = models.ForeignKey('UserType')
        # user_type_id

    关系:

    • something --> usertype 一对多
    • usertype --> userinfo 一对多

    表单中的数据:

    something:

    idname
    1 something1
    2 something2

    usertype:

    idcaptionsomething_id
    1 超级管理员 1
    2 普通管理员 1
    3 黑客 2

    userinfo:

    iduserpwdusertype_id
    1 alex 123 1
    2 eric 123 2

    简要说明

    Django中:

    1. 某表中foreignkey关联另一张表后,会自动在本表单中创建一个名称为另一张表的列:xxx_id
    2. 一对多创建时,foreignkey需要使用在一对多中的多的表单中

    查询

    userinfo_obj = UserInfo.objects.all()

    结果为一个类的列表,类似:[UserInfo对象,UserInfo对象,]

    以上语句会得到的数据为一个元素为查询目标表单对象的列表,所以例子中的userinfo_obj为一个queryset对象我们可以通过`print(userinfo_obj.query)来查看SQL语句.

    取值

    比较简单:

    id = userinfo_obj[0].user.id
    user = userinfo_obj[0].user.user
    pwd = userinfo_obj[0].user.pwd
    ...

    values与vlue_list

    queryset = UserInfo.objects.all().values('user')
    结果:
    [{‘user’: 'alex'},{‘user’: 'eirc'}]
        
    =================================
        
    queryset = UserInfo.objects.all().value_list('user')
    结果:
    [('alex'),('eirc')]

    查询中:

    • 使用values('列名称'),结果为字典组成的列表
    • 使用value_list('列名称'),结果为元组组成的列表

    所以,未来操作中,我们可以使用这两个方便的东西来遍历字典取值还是使用元组取值

    一对多操作

    创建数据

    一般我们是来这么做的:

    UserInfo.objects.create(user='cc','pwd' = '123',user_type=UserType.objects.get(id=2))

    很麻烦吧,其实是两步操作了,但因为建表时有了user_type_id,所以我们可以这么搞:

    UserInfo.objects.create(user='cc','pwd'='123',user_type_id=2)

    很简单吧...

    数据查询

    单表查询:

    UserInfo.objects.filter(user='alex')

    反向查询

    需求:查询所有用户类型等于 普通用户 的所有用户名和密码

    两步操作:

    uid = UserType.objects.filter(caption='普通用户') 
    userinfo_obj = UserInfo.objects.filter(user_type_id=uid)

    两步操作很简单,那就引出了神奇的双下划线:__

    queryset = UserInfo.objcets.filter(user_type__caption='普通用户')
    
    ###结果
    [UserInfo对象,UserInfo对象,UserInfo对象,]
    row = queryset[0] #取到一个元素
    user = row.user
    password = row.pwd #取到具体信息
    row.user_type.id 
    row.user_type.caption

    总结下:

    • 一对多中,正下查询使用foreignkey 的 _id 查询:row.外键字段.外键表的字段
    • 一对多中反向查询,首先还是在在一对多中的多的表单中查询,可以使用__连接相关表中的列名去查询:row__

    其实感觉__有点像关系连线的意思

    queryset = UserInfo.objects.filter(user_type__caption='普通用户').values('user','pwd','user_type__caption')  

    ####结果 [{'user':'alex','pwd':'123','user_type__caption':'普通用户'}{'user':'eric','pwd':'123','user_type__caption':'普通用户'}]

    三张表跨表操作

    跟上面一样,直接用__即可

    queryset = UserInfo.objects.filter(user_type__s__name='xxx')

    进阶操作

    获取个数:

    UserInfo.objects.filter(name = 'alex').count()

    大于小于,还是使用双下划线__

    UserInfo.objects.filter(id__gt=2)#获取ID大于2的数据 
    UserInfo.objects.filter(id__lt=5)#获取ID小余5的数据
    UserInfo.objects.filter(id__gt=2,id__lt=5) #获取ID大于2小于5的数据

    in:

    UserInfo.objects.filter(id__in=[11,22,33])  #获取id等于11、22、33的数据 
    UserInfo.objects.exclude(id__in=[11,22,33]) #not in

    contains(包含):

    UserInfo.objects.filter(name__contains="ven")   #获取name列中包含'ven'的数据 
    UserInfo.objects.filter(name__icontains="Ven") #获取name列中包含'ven'的数据,对大小写不敏感
    UserInfo.objects.exclude(name__icontains="ven") #不包含

    range:

    UserInfo.objects.filter(id__range=[1,10])   #范围,between and ,获取id在1到10范围中的数据

    联表查询

    用原生代码联表:

    from django.db import connection
    cursor = connection.cursor()
    sql = "select sum(d.count) from t_script_detail_desc as d left join t_scripts as s on d.script_id = s.script_id where d.create_time ='%s' and s.script_area = %s" %(one,self.area)
    cursor.execute(sql)
    num=cursor.fetchall()

    有做外键关联的:

    ShareScripts.objects.filter(share_obj__script_area=self.area,share_time__range=[starttime,stoptime]).count()

    没有外键关联的联表,用extra:

    #2个表关联
    num=OperationTask.objects.filter(task_create_time__range=[starttime,stoptime],task_area=x).extra(select={'temp_type_id':'temp_type_id'},tables=['t_operation_templet'], where=['task_temp_id = temp_id']).values('temp_type_id').annotate(c=Count('task_id')).values('temp_type_id','c')
      count = ScriptsDetailDesc.objects.extra(select={'script_id': 'script_id'}, tables=['t_scripts'],where=['t_script_detail_desc.script_id = t_scripts.script_id']).aggregate(Sum('count'))
    #3个表关联
    result=OperationTask.objects.filter(task_create_time__range=[starttime,stoptime]).extra(select={'temp_type_id':'temp_type_id','name':'oper_type_name'},tables=['t_operation_templet','t_operation_types'], where=['task_temp_id = temp_id','temp_type_id = t_operation_types.id']).values('temp_type_id').annotate(c=Count('task_id')).values('name','c')

     没有外键关联的联表,用extra 条件搜索:

    num = ScriptsDetailDesc.objects.filter(create_time=one).extra(
                        tables=['t_scripts'],
                        where=['t_script_detail_desc.script_id = t_scripts.script_id','script_area =%s'],params = [self.area]).aggregate(Sum('count'))
    num = ScriptsDetail.objects.filter(update_time__startswith=one).extra(
                        tables=['t_scripts'],
                        where=['t_script_detail.script_id = t_scripts.script_id','t_scripts.script_area =%s'],params = [self.area]).count()

    部分参考:https://www.cnblogs.com/ccorz/p/5864470.html

    作者:陈耿聪 —— 夕狱

    出处:https://www.cnblogs.com/CGCong/

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    需求变更的种类及应对方式
    SQL Server中连接远程表、查询其它服务器的数据、导入或导出到其它Sql Server服务器数据
    在IE9中MSWC.BrowserType组件无法识别Cookie的问题
    优秀软件的几个重要标准
    对待代码的态度反应着对待自己的态度
    应对企业不断变化的系统
    在SQL中插入®特殊字符
    如何让领导认识到测试的重要性,在沟通时要注意的几点
    男人要补肾,强肾健脑对能持久做程序
    你可能不知道的Visual Studio 2010使用技巧(VS2010的秘密)
  • 原文地址:https://www.cnblogs.com/CGCong/p/9375938.html
Copyright © 2011-2022 走看看