zoukankan      html  css  js  c++  java
  • Django之ContentType组件

    一、需求

      给商品创建优惠券;

      看看下面表结构:

    class Food(models.Model):
        """
        id   name
        1     面条
        """
        name = models.CharField(max_length=32)
    
        def __str__(self):
            return self.name
    
    
    class Fruit(models.Model):
        """
        id     name
        1      苹果
        """
        name = models.CharField(max_length=32)
        coupons = GenericRelation(to="Coupon")  # 定义反向查询字段
    
        def __str__(self):
            return self.name
    
    
    class Coupon(models.Model):
        """
        优惠券表
        id  name    appliance_id    food_id     fruit_id
        1   通用优惠券   null            null        null
        2   冰箱折扣券   1               null        null
        3   电视折扣券   2               null        null
        4   苹果满减卷   null            null        1
        我每增加一张表就要多增加一个字段
        """
        name = models.CharField(max_length=32)
        # 这样写,每增加一张表就要多增加一个字段, 所以我们可以创建第四张表
        appliance = models.ForeignKey(to="Appliance")
        food = models.ForeignKey(to="Food")
        fruit = models.ForeignKey(to="Fruit")

      创建第四张表,改善上面的写法:遇到这种一张表要跟多张表进行外键关联

    class Appliance(models.Model):
        name = models.CharField(max_length=32)
    
    
    class Food(models.Model):
        """
        id   name
        1     面条
        """
        name = models.CharField(max_length=32)
    
        def __str__(self):
            return self.name
    
    
    class Fruit(models.Model):
        """
        id     name
        1      苹果
        """
        name = models.CharField(max_length=32)
        coupons = GenericRelation(to="Coupon")  # 定义反向查询字段
    
        def __str__(self):
            return self.name
    
    
    class Coupon(models.Model):
        """
        优惠券表
        id       name           content_type_id     object_id
        1     面条优惠券             1                 1
        1     苹果优惠券             2                1
        """
        name = models.CharField(max_length=32)
        # 这样写,每增加一张表就要多增加一个字段, 所以我们可以创建第四张表ContentType
        content_type_id =
        object_id = 
    
    
    class ContentType(models.Model):
        # django自带这张表,已经帮我们做好了,就是django的ContentType组件,我们直接拿过来用就行
        """
        id    app_name    model_class
        1      app01         Food
        2      app01         Fruit
        3      app01         Appliance
        """
        pass

      其实django已经帮我写好了这张ContentType表,我们只需要导入使用即可;

    二、使用django自带的ContentType表

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

      当我们的项目做数据迁移后,会有很多django自带的表,其中就有django_content_type表;

    ContentType组件应用:

      -- 在model中定义ForeignKey字段,并关联到ContentType表,通常这个字段命名为content-type

      -- 在model中定义PositiveIntergerField字段, 用来存储关联表中的主键,通常我们用object_id

      -- 在model中定义GenericForeignKey字段,传入上面两个字段的名字

      --  方便反向查询可以定义GenericRelation字段

    from django.db import models
    from django.contrib.contenttypes.models import ContentType
    from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
    class Food(models.Model):
        """
        id   name
        1     面条
        """
        name = models.CharField(max_length=32)
    
        def __str__(self):
            return self.name
    
    
    class Fruit(models.Model):
        """
        id     name
        1      苹果
        """
        name = models.CharField(max_length=32)
        coupons = GenericRelation(to="Coupon")  # 定义反向查询字段
    
        def __str__(self):
            return self.name
    
    class Coupon(models.Model):
        """
        优惠券表
        id       name           content_type_id     object_id
        1     面条优惠券             1                 1
        1     苹果优惠券             2                1
        """
        name = models.CharField(max_length=32)
        # 这样写,每增加一张表就要多增加一个字段, 所以我们可以创建第四张表ContentType
        # appliance = models.ForeignKey(to="Appliance")
        # food = models.ForeignKey(to="Food")
        # fruit = models.ForeignKey(to="Fruit")
    
        # 第一步  先生成ForeignKey字段 关联ContentType
        content_type = models.ForeignKey(to=ContentType)
        # 第二步   生成一个IntergerField 字段关联
        object_id = models.PositiveIntegerField()
        # 第三步 生成一个GenericForeignKey 把上面两个字段注册进去
        content_obj = GenericForeignKey("content_type", "object_id")
    
        def __str__(self):
            return self.name

    基本的操作:

    class Test(APIView):
    
        def get(self, request):
            from django.contrib.contenttypes.models import ContentType
            # 通过contentType获取表名
            content = ContentType.objects.filter(app_label="app01", model="food").first()  # 表名都是小写
            model_class = content.model_class()  # 通过上一步获取的contentType对象获取 里面的表对象
            ret = model_class.objects.all()  # 查询这个表中所有的信息
            print(ret)
    
            # 给Food表中的面条创建一个优惠券
            noodle_obj = models.Food.objects.filter(id=2).first()  # 这里面包含了自己所在的表,和自己这条记录在那张表中的id
            models.Coupon.objects.create(name="面条优惠券", content_obj=noodle_obj)  # 只要传入上面的obj即可
    
            # 查询id为1的优惠券,对应那个商品信息
            coupon_obj = models.Coupon.objects.filter(id=1).first()
            goods_obj = coupon_obj.content_obj  # 拿到对应的商品对象
            print(goods_obj)
            print(goods_obj.name, goods_obj.id)
    
            # 查询苹果的所有优惠券
            # 因为我们定义了反向字段,所以可以这么查:
            # 首先找苹果对象
            apple_obj = models.Fruit.objects.filter(name="苹果").first()
            coupon_obj_list = apple_obj.coupons.all()  # 通过字段反向查询
            print(coupon_obj_list)
            print(coupon_obj_list.first().name)
    
            return Response("ok")

     原作者:https://www.cnblogs.com/glh-ty/p/9703574.html

  • 相关阅读:
    VSCode一键调用DOSBox运行MASM/TASM代码的自定义任务
    C# | VS2019连接MySQL的三种方法以及使用MySQL数据库教程
    Visual Studio 2019连接MySQL数据库详细教程
    Visual Studio 2022 激活码
    Python | 使用SVM支持向量机进行鸢尾花分类
    Python | __init__.py的神奇用法
    Java简单介绍及Java生态
    NoSQL:一个帝国的崛起
    学习哪门语言好
    浅析HTTP协议
  • 原文地址:https://www.cnblogs.com/qq631243523/p/10105178.html
Copyright © 2011-2022 走看看