跨表操作

跨表,基于QuerySet查询时,不用加set,使用神奇的双下划线'__'。values()和values_list()取值的时候也是。

tag_list=models.Tag.objects.filter(blog=blog).annotate(c=Count('article')).values('title','c')

BBS项目中:.annotate分组,前面是什么就表示以什么为分组,以某个博客的所有标签为分组对像。

  annotate(c=Count('article')),聚合,这里用article,因为前面的到的是QuerySet对象,不用article_set。这里用的相当于article__id。

一、一对多跨表:

  1.建表:

 
1 from django.db import models
2 
3 class UserInfo(models.Model):
4     username=models.CharField(max_length=32)
5     password=models.CharField(max_length=32)
6     ut=models.ForeignKey(to='UserType',on_delete=True)
7 class UserType(models.Model):
8     title=models.CharField(max_length=32)
View Code

   2.插入数据:

 1 #创建数据
 2     models.UserType.objects.create(title='人事部')
 3     models.UserType.objects.create(title='财务部')
 4     models.UserType.objects.create(title='公关部')
 5 
 6     models.UserInfo.objects.create(username='杨国伟',password='123',ut_id=1)
 7     models.UserInfo.objects.create(username='石恩光',password='123',ut_id=1)
 8     models.UserInfo.objects.create(username='钱博文',password='123',ut_id=3)
 9     models.UserInfo.objects.create(username='杨理想',password='123',ut_id=2)
10     models.UserInfo.objects.create(username='周腾飞',password='123',ut_id=3)
View Code

  3.正向跨表

    UserInfo中有ForeignKey字段,从UserInfo到UserType是正向跨表,反之是反向跨表。

#三种不同取值方法的跨表操作
1
  obj=models.UserInfo.objects.filter(id=1).first()#获取一个UserInfo对象。结果是一个object 2 print(obj) 3 print(obj.username,obj.password,obj.ut_id,obj.ut.title) 4 obj=models.UserInfo.objects.values('username','password','ut_id','ut__title')#结果是一个字典 5 print(obj) 6 obj=models.UserInfo.objects.values_list('username','password','ut_id','ut__title')#结果是一个元组 7 print(obj)

  运行结果:

  UserInfo object (1)


  杨国伟 123 1 人事部


  <QuerySet [{'username': '杨国伟', 'password': '123', 'ut_id': 1, 'ut__title': '人事部'}, {'username': '石恩光', 'password': '123', 'ut_id': 1, 'ut__title': '人事部'}, {'username': '钱博文',   'password': '123', 'ut_id': 3, 'ut__title': '公关部'}, {'username': '杨理想', 'password': '123', 'ut_id': 2, 'ut__title': '财务部'}, {'username': '周腾飞', 'password': '123', 'ut_id': 3, 'ut__title': '公关部'}]>


  <QuerySet [('杨国伟', '123', 1, '人事部'), ('石恩光', '123', 1, '人事部'), ('钱博文', '123', 3, '公关部'), ('杨理想', '123', 2, '财务部'), ('周腾飞', '123', 3, '公关部')]>

  4.反向跨表

    obj.小写的表名_set

1   obj=models.UserType.objects.filter(id=1).first()
2     print(obj)
3     print(obj.userinfo_set.all())
4     for item in obj.userinfo_set.all():
5         print(item.username,item.password)
6     obj=models.UserType.objects.values('title','userinfo__username','userinfo__password')
7     print(obj)
8     obj = models.UserType.objects.values_list('title', 'userinfo__username', 'userinfo__password')
9     print(obj)

运行结果:  

UserType object (1)
<QuerySet [<UserInfo: UserInfo object (1)>, <UserInfo: UserInfo object (2)>]>
杨国伟 123
石恩光 123
<QuerySet [{'title': '人事部', 'userinfo__username': '杨国伟', 'userinfo__password': '123'}, {'title': '人事部', 'userinfo__username': '石恩光', 'userinfo__password': '123'}, {'title': '公关部', 'userinfo__username': '钱博文', 'userinfo__password': '123'}, {'title': '财务部', 'userinfo__username': '杨理想', 'userinfo__password': '123'}, {'title': '公关部', 'userinfo__username': '周腾飞', 'userinfo__password': '123'}]>
<QuerySet [('人事部', '杨国伟', '123'), ('人事部', '石恩光', '123'), ('公关部', '钱博文', '123'), ('财务部', '杨理想', '123'), ('公关部', '周腾飞', '123')]>

二、多对多

  多对多,需要第三张表来建立关系。

  技巧:

    如果想从不含FK 的表中进行跨表,用object.小写表名_set.all()。小写的表名是含有FK的表。

    从含FK的表中进行跨表,FK名__字段名。字段名是要跨到的那张表的字段名。

  1.创建表

 1 from django.db import models
 2 
 3 class Boy(models.Model):
 4     name=models.CharField(max_length=32)
 6 class Girl(models.Model):
 7     name=models.CharField(max_length=32)
 8 class Love(models.Model):
 9     b=models.ForeignKey('Boy',on_delete=True)
10     g=models.ForeignKey('Girl',on_delete=True)

方法一:

  从不含FK的表进行跨表,_set.all()。得到Love对象。

  obj=models.Boy.objects.filter(id=1).first()
    g_list=obj.love_set.all()#Love对象for item in g_list:
        print(item.g.name)

方法二:

  从Love中进行跨表,__字段名。得到是Love对象。

1   obj_list=models.Love.objects.filter(b__id=1)
2     print(obj_list)
3     for item in obj_list:
4         print(item.g.name)

方法三:

  上面的方发,每次循环都要去数据库查询,进行跨表操作。

  此方法可避免,只进行一次查询,跨表。

   obj_list=models.Love.objects.filter(b__id=1).values('g__name')
    for item in obj_list:
        print(item['g__name'])

 补充:

  创建联合唯一外键,表示Love表中,(b,q)只能出现一次。

  class Love(models.Model):
    b=models.ForeignKey('Boy',on_delete=True)
    g=models.ForeignKey('Girl',on_delete=True)

    class Meta:
        unique_together=[
            ('b', 'g'),
        ]

多对多之Django自动创建第三张表:

from django.db import models

class Boy(models.Model):
    name=models.CharField(max_length=32)
    m=models.ManyToManyField('Girl')#也可以放在Girl中
class Girl(models.Model):
    name=models.CharField(max_length=32)
  往Django自动创建的第三张表boy_m中添加数据。
  由于后台并没有boy_m的类,所以不能用前面添加数据的方法。

  obj=models.Boy.objects.filter(id=1).first() obj.m.add(1) obj.m.add(2,3)

这表示给id=1的boy和id=1,2,3的girl建立关系

  obj=models.Boy.objects.filter(id=1).first()
    obj.m.remove(1)#删除id=1的boy和id=1的girl的关系
    obj.m.remove(2,3)#同上
   obj.m.add(1,2)
    obj.m.set([3])#重置关系,把原来的关系都删除了,然后自设置。
#把id=1的boy和id=1,2的girl的关系删除,然后建立id=1的boy和id=1的girl的关系
1     obj.m.add(1,2)
2     g_list=obj.m.all()#查看所有和id=1的boy有关的girl,得到的是Girl对象
3     print(g_list)
4     for item in g_list:
5         print(item.name)
obj.m.clear()#删除所有id=1的boy的关系

正向查询:

1    obj=models.Boy.objects.filter(id=1).first()
2     g_list=obj.m.all()
3     print(g_list)  #Girl对象
4     for item in g_list:
5         print(item.name)

 反向查询:

  obj=models.Girl.objects.filter(id=2).first()
    obj_list=obj.boy_set.all()
    print(obj_list)#Boy对象
    for item in obj_list:
        print(item.name)

多对多自动创建手动创建第三张表结合:

 1 from django.db import models
 2 
 3 class Boy(models.Model):
 4     name=models.CharField(max_length=32)
 5     m=models.ManyToManyField('Girl',through='Love',through_fields=('b','g'))
 6 class Girl(models.Model):
 7     name=models.CharField(max_length=32)
 8 class Love(models.Model):
 9     b=models.ForeignKey('Boy',on_delete=True)
10     g=models.ForeignKey('Girl',on_delete=True)
11     class Meta:
12         unique_together = [
13             ('b', 'g'),
14         ]

  m=models.ManyToManyField('Girl',through='Love',through_fields=('b','g'))。

  表示同过Love表进行关联,关联的字段(b,g)。切不会自动生成表,会创建Love表。

  其中:上面两种分开的操作,在这里都可以用

给Love表操作时:obj..m.add()/remove()/set()不可以用

        clear(),all()可以用

多对多:自己关联自己。FK

  对男女进行配对,现建一张表,自己关联自己。

  建表的时候,U2U表中,表中第一列是b_id,填男生id,第二列是g_id,填女生id。不可填错,否则关系就出错了。

  related_name:给所属的对象命名,因为是自己关联自己,查找是要知道是男生还是女生对象来查找。

  男生对象.girl.all():就得到所有的和该男生有关的行,是U2U对象。用(.g.name)就得到女生的姓名。女生查找类似。

#测试自己关联自己 FK
class UserInfo(models.Model):
    name=models.CharField(max_length=32)
    username=models.CharField(max_length=32)
    password=models.CharField(max_length=32)
    gender_choose=(
        (1,''),
        (2,''),
    )
    gender=models.IntegerField(choices=gender_choose)
class U2U(models.Model):
    b=models.ForeignKey('UserInfo',on_delete=True,related_name='girl')
    g=models.ForeignKey('UserInfo',on_delete=True,related_name='boy')
  #找所有和该男生相关的女生
  b_obj=models.UserInfo.objects.filter(id=1).first()
    g_list=b_obj.girl.all()
    print(g_list)
    for i in g_list:
        print(i.g.name,i.g.gender)

  自己关联自己。M2M

  这样创建表,django会自动生成以个关系表,出id列还有两列。你需要自己规定第一列填男生id还是女生id。这里规定,第一列男生id,第二列女生id。

这就相当于:一张男生表,一张女生表,男生表里有M2M。

  则查询是就是:男生对象.m.all()

           女生对想.userinfor_set.all()

  #查找和该男生相关的所有女生
    b_obj=models.UserInfo.objects.filter(id=1).first()
    g_list=b_obj.m.all()
    print(g_list)
    for i in g_list:
        print(i.name,i.gender)
    #查找和该女生相关的所有男生
    g_obj=models.UserInfo.objects.filter(id=3).first()
    b_list=g_obj.userinfo_set.all()
    print(b_list)
    for i in b_list:
        print(i.name,i.gender)

 

class UserInfo(models.Model):
    name=models.CharField(max_length=32)
    username=models.CharField(max_length=32)
    password=models.CharField(max_length=32)
    gender_choose=(
        (1,''),
        (2,''),
    )
    gender=models.IntegerField(choices=gender_choose)
    m=models.ManyToManyField('UserInfo')

 

posted @ 2019-08-15 20:24  heart丶real  阅读(400)  评论(1编辑  收藏  举报