Django ContentType组件

一、作用

概念: contenttypes 是Django内置的一个应用,可以追踪项目中所有app和model的对应关系,并记录在ContentType表中

二、应用场景

一张多对一的表,与多张表有对应关系(多对一)

可以通过,给多对一的表添加字段来完成,没有用到的值用空值表示,但这种操作太过于麻烦

思想:

通过创建一张额外的表用于存储表名,

多对一的表

id   ....     xid(单表的id)   oid(额外的表的id)

1               1                     1

2                     2                    1

举例:

-不同种类的课程对应不同的表
-每一类课程,每一个课程,对应多种价格

三、知识点

1、导入模块

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
# Create your models here.

2、在多对一的表中创建三个字段

    # content_type 和 object_id 以及 content_object 的名称是固定的
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    # PositiveIntegerField 正整数
    object_id = models.PositiveIntegerField()

    # 不会在数据库中生成字段, 只用于查询和添加
    content_object = GenericForeignKey('content_type', 'object_id')

3、在一的表中添加

  # policy_list不会在数据库生成,只用于查询
    policy_list = GenericRelation(to="PricePolicy")

4、3个过程

a、在django_content_type中添加表的数据

b、多对一的表与一表产生联系

c、一的表与多对一的表产生联系

四、示例

1、models.py

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
# Create your models here.


class Course(models.Model):
    name = models.CharField(max_length=32, unique=True)
    img = models.CharField(max_length=255)

    # 不会在数据库中产生字段,只用于查询
    policy_list = GenericRelation(to="PricePolicy")

    def __str__(self):
        return self.name


class DegreeCourse(models.Model):
    name = models.CharField(max_length=32, unique=True)
    img = models.CharField(max_length=255)

    # policy_list不会在数据库生成,只用于查询
    policy_list = GenericRelation(to="PricePolicy")

    def __str__(self):
        return self.name


class PricePolicy(models.Model):
    # content_type 和 object_id 以及 content_object 的名称是固定的
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    # PositiveIntegerField 正整数
    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()

2、views.py

from django.shortcuts import render, HttpResponse
from app01.models import Course, DegreeCourse, PricePolicy
# Create your views here.


def test(request):
    # 1.添加数据: 先PricePolicy表中, 添加一条数据
    # PricePolicy.objects.create(
    #     valid_period=7,
    #     price=88.22,
    #     content_object=Course.objects.get(id=1)
    # )
    # # 2.正向查找: 从PricePolicy表中, 查找对应表的数据
    # price_obj = PricePolicy.objects.get(id=1)
    # course_name = price_obj.content_object.name
    # course_img = price_obj.content_object.img
    # print(course_name)
    # print(course_img)
    # 3.反向查找: 从Course表中,找到 在PricePolicy对应的数据
    course_obj = Course.objects.get(pk=1)
    ret = course_obj.policy_list.all()
    li = [{'id': i.id, "价格": i.price, "周期": i.valid_period} for i in ret]
    print(li)
    return HttpResponse('ok')
原文地址:https://www.cnblogs.com/wt7018/p/11543603.html