[django] ContentType使用

如果一張表如price需要跟很多表動態創建ForeignKey關係,如果表price通過創建多個字段來記錄其他表,許多字段會產生空行。通過Django自帶的ContentType,表的行數不變,關聯其他表。

在這裏插入圖片描述

主要有添加兩個字段:
content_type = models.ForeignKey(to=ContentType,on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_type:對象指向某個表的對象,content_type_id 即是ContentType表中的,某表名一一對應的主鍵值。
object_id:是一個正整數,這個值無法與表進行關聯,需要我們自行添加數據。如:

models.PricePolicy.objects.create(
     valid_period=7,
     price=6.6,
     content_type=ContentType.objects.get(model='course'),
     object_id=1
 )

好在ContentType提供了方便我們添加和查詢的字段。

content_object = GenericForeignKey('content_type', 'object_id')

在price表中,添加GenericForeignKey關聯後,我們添加數據只需要對content_object取到對象,無論是哪張表添加,都會給定兩個參數,一個是你要添加的是哪張表,另一個是這個表添加數據的id值,如下,通過Course表id值,我們可以得到該條數據的object_id。

models.PricePolicy.objects.create(
    valid_period=14,
    price=9.9,
    content_object=models.Course.objects.get(id=1)
)

這樣做的目的也很明顯,如果我們這個課程有多個價格策略的話,通過改變其他數據,而id不變,可以很方便的添加多條記錄,即某課程id爲1的數據,python開發,可以指定多個套餐的價格。實現我們的最終目的。

相互查詢可以通過GenericRelation。

models.py

from django.contrib.contenttypes.fields import GenericForeignKey,GenericRelation

class Course(models.Model):
    title = models.CharField(verbose_name="課程名稱",max_length=32)
    course_img = models.CharField(verbose_name="課程圖片",max_length=64)
	
	policy_list = GenericRelation("PricePolicy")

class DegreeCourse(models.Model):
    title = models.CharField(max_length=32,unique=True)
    course_img = models.CharField(max_length=255)
    brief = models.TextField()

class PricePolicy(models.Model):
        content_type = models.ForeignKey(to=ContentType,on_delete=models.CASCADE)
        object_id = models.PositiveIntegerField()
        
        # 不會在數據庫生成列,只用於幫助你進行添加和查詢
        content_object = GenericForeignKey('content_type', 'object_id')

        valid_period_choices = (
            (1, '1天'),(3, '3天'),(7, '1周'), (14, '2周'),(30, '1個月'),(60, '2個月'),
            (90, '3個月'),(180, '6個月'), (210, '12個月'),(540, '18個月'), (720, '24個月'),
        )
        valid_period = models.SmallIntegerField(choices=valid_period_choices)
        price = models.FloatField()

views.py

from django.contrib.contenttypes.models import ContentType


def test(request):
    # 1.在價格策略表中添加一條數據
    models.PricePolicy.objects.create(
        valid_period=7,
        price=6.6,
        content_type=ContentType.objects.get(model='course'),
        object_id=1
    )

    models.PricePolicy.objects.create(
        valid_period=14,
        price=9.9,
        content_object=models.Course.objects.get(id=1)
    )

    # 2. 根據某個價格策略對象,找到他對應的表和數據,如:管理課程名稱
    price = models.PricePolicy.objects.get(id=2)
    print(price.content_object.name) # 自動幫你找到

    # 3.找到某個課程關聯的所有價格策略
    obj = models.Course.objects.get(id=1)
    for item in obj.policy_list.all():
        print(item.id,item.valid_period,item.price)

    return HttpResponse('...')

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