Django models多表操作



title: Django models多表操作
tags: Django

多表操作

單獨創建第三張表的情況

推薦使用的是使用values/value_list,selet_related的方式,查詢效率高

建立表

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


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


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

表建立聯合唯一索引unique_together

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

    # 建立聯合唯一索引
    class Meta:
        unique_together = [
            ('b','g')
        ]
	"""
    通過第三張表查與男生表有關系的女生
    下面是通過男生表反向查詢 使用小寫的表明love_set
    """
    # obj = models.Boy.objects.filter(name='鋼彈').first() # 這里是對象
    # love_list = obj.love_set.all()
    # for item in love_list:
    #     print(item.g.nick)

    """
    通過第三張表正向操作
    """
    # love_list = models.Love.objects.filter(b__name='鋼彈')
    # for item in love_list:
    #     print(item.g.nick)

    """
    但是上面的情況是for循環多次查詢,效率低,
    用values,value_list進行優化,
    values獲得是字典,value_list獲取的是元組
    """
    # love_list = models.Love.objects.filter(b__name='鋼彈').values('g__nick')  # 僅查詢一次
    # print(love_list)  # <QuerySet [{'g__nick': '翠花'}, {'g__nick': '英子'}, {'g__nick': '妞子'}]>
    # for item in love_list:
    #     print(item['g__nick'])  # 這是取字典內容

    # love_list = models.Love.objects.filter(b__name='鋼彈').values_list('g__nick')
    # print(love_list)
    # for item in love_list:
    #     print(item[0])  # 取元組中的內容 取第一個

    """
    使用select_related 進行優化 查詢到的是一個對象
    """
    # love_list = models.Love.objects.filter(b__name='鋼彈').select_related('g') # 直接寫外鍵原來的名字
    # print(love_list)
    # for obj in love_list:
    #     print(obj.g.nick)  # 是通過對象查

使用ManyToManyField 創建表

使用ManyToManyField,Django會自動生成第三張表,但是沒有相應的類,是不能直接操作django自動生成的表的。但是可以通過Boy表關聯的m間接的進行操作。

生成的第三張表示boy_m

class Boy(models.Model):
    name = models.CharField(max_length=32)
    m = models.ManyToManyField("Girl")  # 里面寫的是要關聯的表


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

對第三張表進行增刪改

 	obj = models.Boy.objects.filter(name='鋼彈').first()
    print(obj.id,obj.name)
	
	"""
	增加操作
	"""
    # obj.m.add(2)  # 增加一個 最終增加的是g_id-->  1 2
    # obj.m.add(1,2,3)  # 增加多個
    # obj.m.add(*[4,])  # 使用列表進行接收

	"""
	刪除操作
	"""
    # obj.m.remove(2)  
    # obj.m.remove(1,2,3) 
    # obj.m.remove(*[4,]) 

通過ManyToMany查詢的,關鍵是通過all查詢的是girl的對象

 	obj = models.Boy.objects.filter(name='鋼彈').first()
    print(obj.id,obj.name)
    girl_list = obj.m.all() # 查詢的時候Django自動獲得是girl對象
    print(girl_list)
    for item in girl_list:
        print(item.nick)  # 從對象獲取

還可以繼續進行過濾,filter內部的字段是Girl內部的

 girl_list = obj.m.all().filter(nick='翠花') # 查詢的時候Django自動獲得是girl對象
    for item in girl_list:
        print(item.nick)  # 從對象獲取

修改內容

set是重置

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

清空clear是清空與之關聯的全部

obj.m.clear()

ManyToMany的反向操作

    """
    ManyToMany的反向操作
    小寫的表名_set.all()
    通過Girl取Boy
    """
    obj = models.Girl.objects.filter(nick='翠花').first()
    boy_list = obj.boy_set.all()
    print(boy_list)
    for item in boy_list:
        print(item.name)  # 從對象獲取
``


### 混合使用

ManyToMany的缺陷是只能自動創建3列字段,不能再進行擴展。所以用到了下面的混合使用


不影響第三張表的使用,第三張表還是通過類進行增加刪除

通過ManyToMany增加的是**查詢和清空**的功能



#### 創建

**關鍵是 through  through_fields**,through指定的是自己創建的第三張表,

through_fields指定的是第三張表中的字段

這樣就指定了自己創建第三張表,不通過ManyToMany創建

```python
class Boy(models.Model):
    name = models.CharField(max_length=32)
    m = models.ManyToManyField("Girl",through='Love',through_fields=('b','g'))
    # m = models.ManyToManyField("Girl")


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


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

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

使用

obj.m.clear()
obj.m.all()

中間遇到的錯誤,強制刪除了m表

ValueError: Cannot alter field app01.Boy.m into app01.Boy.m - they are not compatible types (you cannot alter to or from M2M fields, or add o
r remove through= on M2M fields)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM