• ORM之连表操作


    ORM之连表操作

    -----------------------------连表的正向操作-------------------------

      在models.py中创建两张表UserType和UserInfo:

    from django.db import models
    
    class UserType(models.Model):
        """
        用户类型
        """
        title = models.CharField(max_length=32)
    
    class UserInfo(models.Model):
        """
        用户表
        """
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        ut = models.ForeignKey("UserType")

      在views.py中创建数据:

    from django.shortcuts import render,HttpResponse,redirect
    from app01 import models
    
    def data(request):
        """
        UserType表 创建数据
        UserInfo表 创建数据
        :param request:
        :return:
        """
        models.UserType.objects.create(title='普通用户')
        models.UserType.objects.create(title='二逼用户')
        models.UserType.objects.create(title='牛逼用户')
    models.UserInfo.objects.create(name
    ='wang',age=18,ut_id=1) models.UserInfo.objects.create(name='george',age=18,ut_id=2) models.UserInfo.objects.create(name='zhe',age=18,ut_id=3) models.UserInfo.objects.create(name='hahahha',age=18,ut_id=3) models.UserInfo.objects.create(name='gggg',age=98,ut_id=2) models.UserInfo.objects.create(name='llllll',age=38,ut_id=1) return HttpResponse("....")

      在views.py中,获取数据

    from django.shortcuts import render,HttpResponse,redirect
    from app01 import models
    
    def data(request):
        """
        UserType表 创建数据
        UserInfo表 创建数据
        :param request:
        :return:
        """
        #创建数据
        models.UserType.objects.create(title='普通用户')
        models.UserType.objects.create(title='二逼用户')
        models.UserType.objects.create(title='牛逼用户')
        models.UserInfo.objects.create(name='wang',age=18,ut_id=1)
        models.UserInfo.objects.create(name='george',age=18,ut_id=2)
        models.UserInfo.objects.create(name='zhe',age=18,ut_id=3)
        models.UserInfo.objects.create(name='hahahha',age=18,ut_id=3)
        models.UserInfo.objects.create(name='gggg',age=98,ut_id=2)
        models.UserInfo.objects.create(name='llllll',age=38,ut_id=1)
    
        #获取
        #获取UserInfo表的全部数据,是QuerySet类型,列表的存储方式[obj,obj,obj]
        result = models.UserInfo.objects.all()
        #循环result,每一个obj是一行的数据
        for obj in result:
            #在obj里连表UserType
            print(obj.name,obj.age,obj.ut_id,obj.ut.title)
    
        return HttpResponse("....")

      UserInfo和UserType两个表关联,UserInfo的外键连UserType的主键。拿到UserInfo的所有信息,就可以拿与UserInfo相关联的UserType的数据。

    result = model.UserInfo.object.all()

      与UserInfo有关联的UserType表:

    for obj in result:
        print(obj.name,obj,age,obj.ut_id,obj.ut_title)
    
    #ut_id是UserType表的id,ut_title是UserType中的title
    #如果UserType表中,也有Foreigkey字段,也可以继续跨表,接着点就行。

     eg

      在model中:

    from django.db import models
    
    class Foo(models.Model):
        caption = models.CharField(max_length=32)
        
    class UserInfo(models.Model):
        #主键会自行创建,也可自己创建,nid为字段
        nid = models.BigAutoField(primary_key=True)
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=64)
        #增加列,在增加是,可以定义为空,也可定义为默认值
        age = models.IntegerField(null=True)
        # age = models.IntegerField(default=1)
    
        #外键关联UserGroup表,代表UserGroup的一行数据
        usergroup = models.ForeignKey("UserGroup",null=True)
    
    class UserGroup(models.Model):
        #隐藏id,Django的ORM会加的
        title = models.CharField(max_length=32)
        fo = models.ForeignKey('Foo',null=True)
    model

      在views中:  

    from models同级目录文件 import models
    
    def test(request):
        result = models.UserInfo.objects.all()
        print(result)
        for i in result:
            print(i.username,i.usergroup.title,i.usergroup.fo.caption)
    views

     在print(i.username,i.usergroup.title,i.usergroup.fo.caption)中,有跨一张表的,和两张表的。

    i.username:拿的本表的
    
    i.usergroup.title 跨一张表的
    
    i.usergroup.fo.caption 跨两张表的

    在UserInfo中,usergroup是FK字段

    obj = models.UserInfo.object.all().first()

    print(obj.username,obj.password,obj.age,obj.usergroup.title)

    在这里,first是只拿取第一条数据。

    ------- 反向关联表:一个用户类型下可以有很多用户 -------------

    from django.shortcuts import render,HttpResponse,redirect
    from app01 import models
    
    def data(request):
        #创建数据
        models.UserType.objects.create(title='普通用户')
        models.UserType.objects.create(title='二逼用户')
        models.UserType.objects.create(title='牛逼用户')
        models.UserInfo.objects.create(name='wang',age=18,ut_id=1)
        models.UserInfo.objects.create(name='george',age=18,ut_id=2)
        models.UserInfo.objects.create(name='llllll',age=38,ut_id=1)
    
        #获取
        #获取UserInfo表的全部数据,是QuerySet类型,列表的存储方式[obj,obj,obj]
        result = models.UserInfo.objects.all()
        #循环result,每一个obj是一行的数据
        for obj in result:
            #在obj里连表UserType
            print(obj.name,obj.age,obj.ut_id,obj.ut.title)
      
        #反向操作:UserType,表名小写_set.all() 就是反向查找
        obj = models.UserType.objects.all().first()
        print('用户类型',obj.id,obj.title,obj.userinfo_set.all())
        for row in obj.userinfo_set.all():  #obj是UserType表的别名,obj.userinfo_set可以查到UserInfo里的数据。通过UserType找UserInfo。
            print(row.name,row.age)
        return HttpResponse("....")

      只要表有外键,就会有一个不显示字段的_set数据,拿UserType说,_set反向查到的是所用属于某一个ID字段的数据。  

    result = model.UserType.object.all()
    for item in result:
        print(item.title,item.userinfo_set.filter(name='george'))  #这里还可以.filter
        #这里item.userinfo_set.all 是拿到每个用户类型的所用相关数据。
        #但是.filter是在每个用户类型里的用户数据,进行二次筛选。

      在去ORM中拿数据时,单个数据是obj类型。多个数据是QuerySet 列表类型。

      但是,在生产中,会有如下的个别情况:

      其一:

    result = models.UserInfo.object.all().values("id","name") #values里写UserInfo的字段名,作为值。这样就只取id列和name列

      但问题点在于,这个类型是什么。他是一个字典的QuerySet类型:

    #QuerySet[{'id':'XXX','name':'george'}]
    #这是for循环result:
    for row in result:
        print(row)
    
    #其print的结果是字典的形式。

      其二:

    result = models.UserInfo.object.all().values_list("id","name") #这里拿到的values_list是元祖类型

      这个values_list 是元组类型。

    #QuerySet[(1,'george')]
    for row in result:
        print(row)

    #其结果是元组的形式呈现。

      所以,数据获取多个数据时,分三个情况:

      1、QuerySet类型是基本的Set类型:查询数据时的方式。

    #[obj,obj,obj,]
    models.UserInfo.objects.all()
    models.UserInfo.objects.filter(id__gt=1)

      每一个基本的QuerySet类型是可以for循环点出表里的是字段: 

    result = models.UserInfo.object.all()
    for item in result:
        print(item.id,item.name,item.ut.title)  

      2、QuerySet类型是列表的,正反向查询:

    #[{id:1,name:fd},{id:2,name:ffdd},{id:3,name:fffddd},]
    models.UserInfo.objects.all().values("id","name")
    models.UserInfo.objects.filter(id__gt=1).values("id":"name")

      每个QuerySet类型是字典,在跨表查询时,就会遇到问题,解决方法是在查询时就做好跨表操作。

      关键操作是在ut跨表时用双下划线“__”。  

    result = models.UserInfo.object.all().values("id","name","ut__title")
    for item in result:
        print(item["id"],item["name"],item["ut__title"]) 

      3、QuerySet类型是字典和元组,连表要加双下划线“__”

    #[(1,"df"),(2,"ddff"),(3,"dddfff"),]
    models.UserInfo.objects.all().values_list(id"","name")
    models.UserInfo.objects.filter(id__gt=1).values_list("id":"name")

      QuerySet类型是元组,操作方式和字典类似。 

    result = models.UserInfo.object.all().values_list("id","name","ut__title")
    for item in result:
        print(item[0],item[1],item[2]) 

      在反向连表中,关于连表取值的个数问题:

       values和values_list 的操作一样。反向操作都是直接小写表名

        v = models.UserType.objects.values("id","title")
        #这样是UserType表有几行数据就拿几行数据
    
        v = models.UserType.objects.values("id","title","userinfo")
        #这样是以UserInfo和UserType的数据去获取,所以行数是不一样的,因为UserInfo和UserType有关联关系。所以有关联关系的数据有多少行,就拿多少行。然后在单独获取UserInfo没有关联的UserType的字段。
    
         v = models.UserType.objects.values("id","title","userinfo__name")
         #双下划线也可以用在这里进行使用。

      所以在前面的表,比如UserType,都会显示拿到的所以数据。

    -------- END --------

  • 相关阅读:
    Hadoop Gateway 部署
    java 命令--备忘
    整理下常用硬件性能参数
    python 脚本备份 mysql 数据库到 OSS
    pip 更换国内源
    记录闭包和立即执行函数
    Django 中文乱码问题&富文本显示
    mysql exceeded the 'max_questions' resource 记录
    sql server 数据字典的妙用
    Sublime Text指南
  • 原文地址:https://www.cnblogs.com/george92/p/8506259.html
Copyright © 2020-2023  润新知