django-ORM多对多查询 自定义第三张表&ManyToManyField

http://blog.csdn.net/maidou931019/article/details/74852536


https://docs.djangoproject.com/en/2.0/ref/models/fields/#django.db.models.ManyToManyField.through


Django-ORM多对多查询 (自定义第三张表&ManyToManyField)

原创 2017年07月08日 19:56:54

对于多对多表
- 1.自定义第三张表,更加灵活
- 2.ManyToManyField 自动生成第3张表 只能 有3列数据 不能自己添加。


  • 自定义第三张表

# models.py

class Boy(models.Model):
    name = models.CharField(max_length=32)

class Girl(models.Model):
    name = models.CharField(max_length=32)


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

    # 创建联合唯一索引
    # class Meta:
    #     unique_together = [
    #         ('b','g'),
    #     ]




# views.py

def test(request):
    # objs = [
    #     models.Boy(name='summer'),
    #     models.Boy(name='spring'),
    #     models.Boy(name='autumn'),
    # ]
    # models.Boy.objects.bulk_create(objs,5)

    # objs = [
    #     models.Girl(name='小于'),
    #     models.Girl(name='小秋'),
    #     models.Girl(name='小夏'),
    # ]
    # models.Girl.objects.bulk_create(objs,5)

# 查询和girl小于有关系的boy

# 1 通过girl表进行反向查找
    obj = models.Girl.objects.filter(name='小于').first().love_set.all()
    # obj = models.Girl.objects.filter(name='小于').first().love_set.select_related('b').all()
    for i in obj:
        print(i.b.name)




    print(' '.center(60,'='))



# 2 通过Love表进行查找

    obj = models.Love.objects.filter(g__name='小于').all()
    for i in obj:
        print(i.b.name)

    # 这样进行查询性能不好,需要重新发sql请求在进行查询另外一张表中的数据

    boy_list = models.Love.objects.filter(g__name='小于').values('b__name')
    for i in boy_list:
        print(i['b__name'])

    # 这样 进行了 优化 不会重复发送sql请求,查询到的结果内是字典

    boy_obj = models.Love.objects.filter(g__name='小于').select_related('b').all()
    for i in boy_obj:
        print(i.b.name)
    # select_related('ut') 相当 于 inner join 先连成一张表再进行查询

    return HttpResponse('insert ok ....')



  • ManyToManyField

# models.py
from django.db import models

class Boy(models.Model):
    name = models.CharField(max_length=32)
    # m = models.ManyToManyField('Girl')

class Girl(models.Model):
    name = models.CharField(max_length=32)
    m = models.ManyToManyField('Boy')

# views.py

def test(request):
    # objs = [
    #     models.Boy(name='summer'),
    #     models.Boy(name='spring'),
    #     models.Boy(name='autumn'),
    # ]
    # models.Boy.objects.bulk_create(objs,5)

    # objs = [
    #     models.Girl(name='小于'),
    #     models.Girl(name='小秋'),
    #     models.Girl(name='小夏'),
    # ]
    # models.Girl.objects.bulk_create(objs,5)


    # ManyToManyField

    obj = models.Girl.objects.filter(name='小秋').first()

    # 增
    # obj.m.add(3)
    # obj.m.add(3,4)
    # obj.m.add(*[1,2])

    # 删
    # obj.m.remove(3)
    # obj.m.remove(3,4)
    # obj.m.remove(*[1,2])

    # 改
    # obj.m.set([1,2,])

    # boy_obj = obj.m.all()
    # for row in boy_obj:
    #     print(row.id,row.name)
    # 清除
    # obj.m.clear()


    # 反向查 在没有 ManyToManyField 字段的表中查
    obj = models.Boy.objects.filter(name='summer').first()
    girl_obj = obj.girl_set.all()
    # 增删改查
    obj.girl_set.set([1,2,3])

    for row in girl_list:
        print(row.id,row.name)

    return HttpResponse('ok')


  • 杂交(自定义第三张表+ManyToManyField)
# modles.py
class Boy(models.Model):
    name = models.CharField(max_length=32)

class Girl(models.Model):
    name = models.CharField(max_length=32)
    m = models.ManyToManyField('Boy',through='Love',through_fields=('b','g')) # 只让其生成3张表,如果不加后面产生生成4张表

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

# views.py
def test(request):
    obj = models.Girl.objects.filter(name='小于').first()
    # obj.m.add(1) # 不行
    # obj.m.remove(1) # 不行
    # obj.m.set([1,2]) # 不行
    # obj.m.clear() # 可以
    # obj.m.all() # 可以

    # 杂交的方法对获取查询方便点,还添加了清空功能

    boy_obj = obj.m.all()

    for i in boy_obj:
        print(i.name)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
版权声明:本文为博主原创文章,未经博主允许不得转载。 http://blog.csdn.net/maidou931019/article/details/74852536





对比发现 m = models.ManyToManyField( 'Boy' ,through= 'Love' ,through_fields=( 'b' , 'g' ))
其中through_fields=('b','g')的顺序错了:
应该是through_fields=('g','b')

from django.db import models

class Person ( models . Model ):
   
name = models . CharField ( max_length = 50 )

class Group ( models . Model ):
   
name = models . CharField ( max_length = 128 )
   
members = models . ManyToManyField (
       
Person ,
       
through = 'Membership' ,
       
through_fields = ( 'group' , 'person' ),
   
)

class Membership ( models . Model ):
   
group = models . ForeignKey ( Group , on_delete = models . CASCADE )
   
person = models . ForeignKey ( Person , on_delete = models . CASCADE )
   
inviter = models . ForeignKey (
       
Person ,
       
on_delete = models . CASCADE ,
       
related_name = "membership_invites" ,
   
)
   
invite_reason = models . CharField ( max_length = 64 )
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值