• Django中content-type组件


    django-content

    1.需求

    • 一家餐馆,有多个菜系,粤菜、湘菜、闽南菜、东北菜等,每个菜系中的菜品又分为小份、中份、大份,每个菜系对应的菜品量价格不同,现需要将该需求建表。

    2. 建表方式

    方案一:每个菜系一张表,每个菜系的价格对应一张表,每增加一个菜系都会增加一张表

    方案二:方案一的基础上简单升级版,每个菜单表和第三张表关联,此时每增加一个菜系,价格表需要增加一个字段

    方案三:方案二的基础上升级,添加菜系字段,这样不需要变更表结构,也不需要新增表

    当我们简单创建两张表时候可以发现,django中有一个django_content_type表,里面存了app和对应表的关系。

    方案四:通过django_content_type表修改

    models.py

    from django.db import models
    from django.contrib.contenttypes.models import ContentType
    ​
    class YueCai(models.Model):
        """粤菜"""
        dish_name = models.CharField(max_length=32)
    ​
    class XiangCai(models.Model):
        """湘菜"""
        dish_name = models.CharField(max_length=32)
    ​
    class Price(models.Model):
        """价格表"""
        fenliang = (
            (1, "大份"),
            (2, "中份"),
            (3, "小份"),
        )
        weight = models.IntegerField(choices=fenliang)
        price = models.DecimalField(8,2)
        content_type = models.ForeignKey(ContentType,verbose_name="关联菜系名",on_delete=models.CASCADE)
        dish_id = models.IntegerField(verbose_name="关联各个菜系中菜品id")
    models.py

    自定义插入数据

    from app02 import models
    ​
    def test(request):
        # 为粤菜中冰镇花蟹的大份添加价格为299的数据
        yobj = models.YueCai.objects.filter(dish_name="冰镇花蟹").first()
        cobj = models.ContentType.objects.filter(model="yuecai").first()
        # 我们自己去写需要写每个字段
        models.Price.objects.create(weight=1,price=299,dish_id=yobj.id,content_type_id=cobj.id)
    ​
        obj_set = models.Price.objects.all().values()
        return HttpResponse(obj_set)
    views.py

    3.content-type组件的使用

    为粤菜中冰镇花蟹的大份添加价格为299的数据

    # models.py
    from django.db import models
    from django.contrib.contenttypes.models import ContentType
    from django.contrib.contenttypes.fields import GenericForeignKey
    ​
    class YueCai(models.Model):
        """粤菜"""
        dish_name = models.CharField(max_length=32)
    ​
    class XiangCai(models.Model):
        """湘菜"""
        dish_name = models.CharField(max_length=32)
    ​
    class Price(models.Model):
        """价格表"""
        fenliang = (
            (1, "大份"),
            (2, "中份"),
            (3, "小份"),
        )
        weight = models.IntegerField(choices=fenliang)
        price = models.DecimalField(8,2)
        content_type = models.ForeignKey(ContentType,verbose_name="关联菜系名",on_delete=models.CASCADE)
        dish_id = models.IntegerField(verbose_name="关联各个菜系中菜品id")
        # 不会改变表结构,只是为了帮助我们快速实现content-type操作
        content_obj = GenericForeignKey('content_type','dish_id')
    models.py
    # views.py
    from django.shortcuts import render,HttpResponse
    from app02 import models
    ​
    def test(request):
        # 为粤菜中冰镇花蟹的大份添加价格为299的数据
        # 我们只需要直接插入冰镇花蟹这个数据对象,给到content_obj,会通过yobj对象自动去content_type表中找到YueCai对应的id,和yobj对象id插入数据库中
        yobj = models.YueCai.objects.filter(dish_name="冰镇花蟹").first()
        models.Price.objects.create(weight=1,price=299,content_obj=yobj)
    ​
        obj_set = models.Price.objects.all().values()
        return HttpResponse(obj_set)
    views.py

    通过粤菜中的冰镇花蟹找到对应的价格

    # models.py
    from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
    from django.db import models
    from django.contrib.contenttypes.models import ContentType
    ​
    class YueCai(models.Model):
        """粤菜"""
        dish_name = models.CharField(max_length=32)
        coupons = GenericRelation(to="Price")  # 定义反向查询字段,数据库中不会添加新的列
    class XiangCai(models.Model):
        """湘菜"""
        dish_name = models.CharField(max_length=32)
        coupons = GenericRelation(to="Price")  # 定义反向查询字段,数据库中不会添加新的列
    class Price(models.Model):
        """价格表"""
        fenliang = (
            (1, "大份"),
            (2, "中份"),
            (3, "小份"),
        )
        weight = models.IntegerField(choices=fenliang)
        price = models.IntegerField()
        content_type = models.ForeignKey(ContentType,verbose_name="关联菜系名",on_delete=models.CASCADE)
        object_id = models.IntegerField(verbose_name="关联各个菜系中菜品id")
        # 不会改变表结构,只是为了帮助我们快速实现content-type操作
        content_obj = GenericForeignKey('content_type','object_id')
    models.py
    # views.py
    from django.shortcuts import render,HttpResponse
    from app02 import models
    ​
    def test(request):
        # 通过粤菜中的冰镇花蟹找到对应的价格
        obj_list = models.YueCai.objects.filter(dish_name="冰镇花蟹")
        for obj in obj_list:
            # obj.coupons.all()获取到关联的Price的价格对象列表
            print(obj.coupons.all()) # <QuerySet [<Price: Price object (13)>]>
            for price_obj in obj.coupons.all():
                print(f"份量:{price_obj.get_weight_display()}")
                print(f"价格:{price_obj.price}")
                print(f"菜系:{price_obj.content_type}")
                print(f"菜名:{price_obj.content_obj.dish_name}")
        return HttpResponse("查询成功")
    views.py

    总结:content-type组件适用于,多张表外键关系关联到同一张表的场景,且并不能选择那张表的所有数据,即:价格表中的所有数据并不是都关联粤菜表,只有一部分关联。GenericForeignKey用于正向关联用,GenericRelation用于反向关联用。

     

  • 相关阅读:
    spring boot-17.RabbitMQ
    spring boot-16.使用redis做缓存
    spring boot-15.缓存
    spring boot-14.集成MyBatis
    spring boot-13.数据访问
    docker 安装完mysql 后客户端无法访问
    【python】string functions
    【转】澄清P问题、NP问题、NPC问题
    ubuntu中使用gensim+word2vec[备忘]
    ubuntu熟悉过程中遇到一些小问题记录一下
  • 原文地址:https://www.cnblogs.com/liuweida/p/11763978.html
Copyright © 2020-2023  润新知