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