如果一張表如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('...')