django中的content_type

一。應用場景:

現在有3張表映射(一對多)一張表:表1,2,3一對多表4,每種車都有自己的價格策略

表1:巴士(Bus) →  字段:id,name

表2:出租車(Taxi) → 字段:id,name

表3:地鐵(Metro) → 字段:id,name

表4:價格策略(PrecePolicy) → 字段:id,price,period,對應的車的表名稱,id(對應表名稱的行id)

 二。原始解決方案:

表1,2,3分別創建,表4的創建爲:

class PricePolicy(models.Model):
    """
    價格策略
    """
    price = models.IntegerField()
    period = models.IntegerField()

    table_name = models.CharField(verbose_name="關聯的表名稱")
    object_id = models.CharField(verbose_name="關聯的表中數據行的id")

缺點:這樣創建和修改表比較麻煩

三。最終解決方案

1. 添加content_type字段,用來通過contentType表關聯車型表

2. 添加object_id字段,用來關聯車型表中的某一行

3. 添加content_object字段,用來使以上兩個表關聯起來

from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

class PricePolicy(models.Model):
    """
    價格策略
    """
    price = models.IntegerField()
    period = models.IntegerField()

    content_type = models.ForeignKey(ContentType, verbose_name="關聯的表名稱", on_delete=models.CASCADE)
    object_id = models.IntegerField(verbose_name="關聯的表中數據行的id")
    # 以下字段不添加數據表的列數,只幫助快速實現content_type操作
    content_object = GenericForeignKey('content_type', 'object_id')


使用:

1. 爲某一類型的車添加價格,也就是往PrecePolicy中添加數據

1.1 先獲取bus的對象,可以根據任意途徑獲取

1.2 再添加PricePlicy,這裏只設置content_object參數和PricePlicy的字段就好了

# 先獲取bus的對象,可以根據任意途徑獲取
obj  = models.Bus.objects.filter(name = 'mini').first() 

# 再通過PricePlicy進行添加,這裏只設置content_object參數就好了
models.PricePolicy.objects.create(price=29.9, period=90, content_object=obj)

2. 根據車型id獲取車型,並獲取該車型的所有價格策略

2.1 先在表類中加入GenericRelation關聯反向查找的表

2.2 在view視圖函數中,先獲取要查找的車型對象

2.3 再通過車型獲取所有的價格策略

from django.contrib.contenttype.fields import GenericRelation

class Bus(models.Model):
    name = models.CharField(max_length=32)
    
    # 這個字段不用於生成表字段,只用於反向查找
    price_policy_list = GenericRelation("PricePolicy")


# 先獲取車型
bus = models.Bus.objects.filter(id=1).first()

# 再通過車型獲取所有的價格策略
bus.price_policy_list.all()

3. 刪除車型,或者刪除某一車型的某一行價格

3.1 刪除車型:

只需要找出車型對象,執行delete()操作就性了,不過會把這個車型關聯的價格策略全部刪除

Bus.objects.filter(id=1).delete()

3.2 刪除某車型的某一行價格:

# 先獲取某一車型對象
busObj = Bus.objects.filter(id=1)

# 通過車型對象獲取然後篩選所有要刪除的價格
allBusPrice = busObj.price_policy_list.filter(price=30)

# 刪除
allBusPrice.delete()

只需要找出某車型的所有對象,再通過filter過濾找到要刪除的價格,執行delete()就可以了

4. 修改某車型的數據,或者修改某車型的某一行數據

4.1 修改車型:

只要找出某車型對象,然後修改,然後執行save()就行了(id還是關聯contenttype表的,所以修改name不怕)

# 這裏添加first表示獲取對象而不是queryset
busObj = Bus.objects.filter(id=1).first() 
# 修改字段數據
busObj.name = 'big'
# 保存修改
busObj.save()

4.2 修改某車型的某一行數據

先找出某車型對象對應的價格的所有對象,再通過filter過濾找到要修改的價格對象,然後修改,保存就行了

# 獲取bus對象
busObj = Bus.objects.filter(id=1).first() 

# 通過車型對象獲取然後篩選要修改的價格對象(多個也可以,用循環就行)
changeBusPrice = busObj.price_policy_list.filter(price=30).first()

# 修改價格
changeBusPrice.price = 50

# 保存
changeBusPrice.save()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章