[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('...')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Moke丶青

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值