美文网首页
一个模糊的问题,梳理清楚

一个模糊的问题,梳理清楚

作者: 词穷又词贫 | 来源:发表于2017-08-20 12:49 被阅读91次

    django模型中一对多与多对多关系梳理,三天时间慢慢梳理完。

    一对多关系即是数据库中外键约束。
    多对多关系既是数据库中两个表关联形成多对多关系(通过中间表,将在此表中设置两个外键字段分别为另外两张表的主键)。

    问题:
    1、如何在django模型中建立此类关联关系?又是如何反应到实际数据库中?
    2、在视图中如何利用模型类操作数据库?
    3、在关联关系中,如何更新数据库?(多对多关系)
    4、在关联关系中,如何查询数据库?(多对多关系)
    5、在关联关系中,如何进行多级关系深度查询?(一对多,多对多分开讲)

    练习数据库

    1,2问题比较简单,直接上代码:

    1、问题解答:
    # 主机表
    class Host(models.Model):
        id = models.AutoField(primary_key=True)
        hostname = models.CharField(max_length=50)
        lanip = models.GenericIPAddressField()
    
        class Meta:
            managed = True
            db_table = 'host'
    
    # 主机组表
    class HostGroup(models.Model):
        hgid = models.AutoField(primary_key=True)
        hgname = models.CharField(max_length=50)
        hginfo = models.CharField(max_length=200,default='null')
        hosts = models.ManyToManyField(Host)
    
        class Meta:
            managed = True
            db_table = 'hostgroup'
    
    # 用户组表
    class UserGroup(models.Model):
        gid = models.AutoField(primary_key=True)
        groupname = models.CharField(max_length=50)
        ginfo = models.CharField(max_length=200,default='null')
        userpri = models.BooleanField(default=False,null=False)
        grouppri = models.BooleanField(default=False,null=False)
        hgrouppri = models.BooleanField(default=False,null=False)
        hostgroups = models.ManyToManyField(HostGroup)
    
        class Meta:
            managed = True
            db_table = 'usergroup'
    
    # 角色表
    class Role(models.Model):
        name = models.CharField(max_length=10)
        class Meta:
            managed = True
            db_table = 'role'
    
    # 用户表
    class User(models.Model):
        uid = models.AutoField(primary_key=True)
        username = models.CharField(max_length=50)
        password = models.CharField(max_length=50)
        user = models.CharField(max_length=50)
        role = models.ForeignKey(Role,default=1)
        groups = models.ManyToManyField(UserGroup)
    
        class Meta:
            managed = True
            db_table = 'user'
      # 解释:
      # Role与User表建立一对多关联关系
      # 其他表之间建立多对多关联关系,比如User与UserGroup表之间,是在User类中定义一个名字为groups的类属性,利用ManyToManyField多对多关系关联两表,此类型字段只需要在两张表中任意一张表定义即可,无需两张表都定义,模型的管理器会自动在数据库中建立中间表来实现。
      # 数据库中,表情况:
    
    数据库表 多对多关系表生成中间表
    2、问题解答:(访问test接口测试更新数据)

    1、利用模型对象更新数据(无外键):

    def test(request):
        for i in xrange(1,4):
            rl = Role()
            rl.name = "role" + str(i)
            rl.save()
        return HttpResponse("data")
    # 往role表中插入数据,定义Role对象,字段,对象调去save()方法即可,模型管理器会自动识别你是否在此类中定义主键,如果没有会自动添加id字段为主键,自增长。
    

    2、利用模型对象更新数据(有外键):

    def test(request):
        # for i in xrange(1,4):
        #     rl = Role()
        #     rl.name = "role" + str(i)
        #     rl.save()
    
        for i in xrange(1,15):
            if i <= 3:
                rl = Role.objects.get(pk=1)
                us = User()
                us.username = 'admin' + str(i)
                us.password = 'admin' + str(i)
                us.user = 'neo' + str(i)
                us.role = rl
                us.save()
            elif 3 < i <= 7:
                rl = Role.objects.get(pk=2)
                us = User()
                us.username = 'admin' + str(i)
                us.password = 'admin' + str(i)
                us.user = 'neo' + str(i)
                us.role = rl
                us.save()
            elif 7 < i <= 10:
                rl = Role.objects.get(pk=3)
                us = User()
                us.username = 'admin' + str(i)
                us.password = 'admin' + str(i)
                us.user = 'neo' + str(i)
                us.role = rl
                us.save()
      # 利用模型类对象更新具有外键约束表时,需要先创建外键约束对应对象,接在在更新到表中,否则会失败。
    
    3、问题解答:(一对多关系是外键约束更新数据上面既是)

    关联管理器在一对多,多对多的关联上下文中使用的管理器:
    ForeignKey关系:(一对多关系)

    class Role(models.Model):
        # ...
        pass
    class User(models.Model):
        role = models.ForeignKey(Role)
    # 这样,管理器可以使用role.user_set方法。
    

    ManyToMany关系:(多对多关系)

    class UserGroup(models.Model):
        # ...
        pass
    class User(models.Model):
        groups = models.ManyToManyField(UserGroup)
    # 这样,管理器可以使用usergroup.user_set和user.groups方法。
    

    多对多关联关系更新数据:先将host,hostgroup,usergroup数据填充上。

    # 填充host数据
    for i in xrange(1,10):
        ser = Host()
        ser.hostname = "hostname" + str(i)
        ser.lanip = "10.10.10." + str(i)
        ser.save()
    # 填充hostgroup数据
    for i in xrange(1,5):
        hg = HostGroup()
        hg.hgname = "hg" + str(i)
        hg.hginfo = "hginfo" + str(i)
        hg.save()
    # 填充usergroup数据
    for i in xrange(1,5):
        ug = UserGroup()
        ug.groupname = 'ugname' + str(i)
        ug.save()
    

    多对多关联关系更新数据:
    比如User与UserGroup表之间的多对多关系。

    # 获取用户组对象
    ug1 = UserGroup.objects.get(pk=1)
    ug2 = UserGroup.objects.get(pk=2)
    ug3 = UserGroup.objects.get(pk=3)
    ug4 = UserGroup.objects.get(pk=4)
    # 获取用户对象
    u1 = User.objects.get(pk=1)
    u2 = User.objects.get(pk=2)
    u3 = User.objects.get(pk=3)
    u4 = User.objects.get(pk=4)
    u5 = User.objects.get(pk=5)
    u6 = User.objects.get(pk=6)
    u7 = User.objects.get(pk=7)
    u8 = User.objects.get(pk=8)
    u9 = User.objects.get(pk=9)
    u10 = User.objects.get(pk=10)
    # 多对多关系数据更新:
    # 例一:将ug1用户组关联u1~u3这个三个用户。
     ug1.user_set.add(u1,u2,u3)    # 利用user_set方法
     数据库表展示:
    
    用户与用户组关联关系表
    # 反之例二:将u4这个用户,关联到ug2,ug3,ug4这三个用户组中。
    u4.groups.add(ug2,ug3,ug4)   # 利用groups这个类属性
    数据库表展示:
    
    用户与用户组关联关系表
    # 例三:移除关联对象的关联关系
    # 将用户id 4的用户从用户组4中移除
    ug4.user_set.remove(u4)    # 从ug4角度移除
    u4.groups.remove(ug4)    # 从u4角度移除
    # 两种方式效果一样
    # 数据库展示:
    
    关联关系移除
    4、问题解答:多对多关联关系查询
     # 例:查找用户组ug1中,关联的所有用户组
    ug1 = UserGroup.objects.get(pk=1)
    users = ug1.user_set.all()
    lu = []
    for u in users:
        lu.append(u.user)
    return HttpResponse(lu) 
    
    用户组ug1中的用户

    数据库确认:


    用户组ug1中的用户
    5、问题解答:多级关联关系查询
    建立用户组,主机组,主机表关联关系。
    h1 = Host.objects.get(pk=1)
    h2 = Host.objects.get(pk=2)
    h3 = Host.objects.get(pk=3)
    h4 = Host.objects.get(pk=4)
    h5 = Host.objects.get(pk=5)
    h6 = Host.objects.get(pk=6)
    h7 = Host.objects.get(pk=7)
    h8 = Host.objects.get(pk=8)
    hg1 = HostGroup.objects.get(pk=1)
    hg2 = HostGroup.objects.get(pk=2)
    ug1 = UserGroup.objects.get(pk=1)
    ug1.hostgroups.add(hg1,hg2)
    hg1.hosts.add(h1,h2,h3,h4)
    hg2.hosts.add(h5,h6,h7,h8)
    return HttpResponse("hehe")
    # 主机h1~h4关联到hg1中,h5~h8关联到hg2中。
    # 用户组ug1 关联hg1与hg2两个主机组
    

    数据库展示


    关联关系展示
    例一:查询role id 为1 的所有用户的,所有用户组的,所有主机组的,所有主机。也就是从role表,查到host表。
    
        hostset = Host.objects.filter(hostgroup__usergroup__user__role=1)
        host = []
        for i in hostset:
            host.append(i.hostname)
            host.append('\n')
        return HttpResponse(host)
    

    查询结果:


    查询结果

    role id 为1的用户有admin1,admin2,admin3,所属的组是usergroup1,关联的主机组有hostgroup1,hostgroup2,其中hostgroup1中有主机hostname1,2,3,4 另外hostgroup2中有主机hostname5,6,7,8,所以查询结果是正确。

     例二:查询host id 为1 的主机,所属的关联用户,也就是从host表,查到user表。
    users = User.objects.filter(groups__hostgroups__hosts=1)
    user = []
    for i in users:
        user.append(i.user)
        user.append('\n')
    return HttpResponse(user)
    # 查询结果:
    
    查询结果

    # 以上两例子是从不同方向使用关联对象查询,注意:user.groups与usergroup.user_set方法的使用。

    总结:

    1、django中模型通过模型管理器objects(默认,可以重写),操作数据库。
    2、模型使得数据库操作对象抽象为python语言的类对象,并且将一对多关系与多对多关系,抽象成为两个对象之间的关联关系。
    3、利用模型封装好的user.groups与usergroup.user_set方法,来实现多对多关系的操作,具体操作方法有(add(),remove(),create(),clear())
    4、操作关联对象关系的深度是无限制的,只要两个对象之间至少存在一条关联关系链即可,相互查询。

    自己提问自己,自己解答问题。

    参考官方文档:
    https://docs.djangoproject.com/en/1.11/
    https://docs.djangoproject.com/en/1.11/ref/models/instances/
    https://docs.djangoproject.com/en/1.11/ref/models/relations/

    相关文章

      网友评论

          本文标题:一个模糊的问题,梳理清楚

          本文链接:https://www.haomeiwen.com/subject/ffxfdxtx.html