ContentType使用

场景, 给商品添加优惠券

from django.db import models


class Food(models.Model):
    """
    id      title
     1       面包
     2       馒头
    """
    title = models.CharField(max_length=32)


class Fruit(models.Model):
    """
    id      title
     1       苹果
     2       橘子
    """
    title = models.CharField(max_length=32)


"""
对于以上两张表, 现在要为每个食品添加对应的优惠券
那么普通的想法怎么做呢?
id      title       food_id   fruit_id
1       面包优惠券     2         null
2       水果优惠券     null      2
这样通过外键的联系可以实现功能, 但是问题来了>>>
如果商品类型特别对, 我一个面包的优惠券就要对应除了自己能用到的字段,剩下的都是无用的字段.别的商品也类似
>>>改进<<<
改进的方法就是, 列外新建一张MyTable的表格, 记录app的名字, 和表的名字
id      title       MyTable_id      object_id
1       馒头          1               2
2       橘子          2               2
这张表记录的东西就是MyTable_id对应的appname和tablename,来确定是哪张表, object_id, 确定这张表的那个物品
对于以上的实现方式, DRF给出了这张表格, 记录app和表的对应关系(django_content_type)
"""

# class MyTable(models.Model):
#     """
#     id      appname     tablename
#     1         app02         Food
#     2         app02         Fruit
#     """
#     # 放app的名字
#     app_name = models.CharField(max_length=32)
#     # 表名字
#     table_name = models.CharField(max_length=32)

使用ContentType解决

ContentType组件

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

ContentType组件应用

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

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

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

  - 方便反向查询可以定义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      title
     1       面包
     2       馒头
    """
    title = models.CharField(max_length=32)


class Fruit(models.Model):
    """
    id      title
     1       苹果
     2       橘子
    """
    title = models.CharField(max_length=32)


class Appliance(models.Model):
    name = models.CharField(max_length=64)
    coupons = GenericRelation(to="Coupon")


class Coupon(models.Model):
    name = models.CharField("活动名称", max_length=32)
    # 第一步 代表那个app下的那张表
    content_type = models.ForeignKey(to=ContentType, null=True, blank=True)
    # 第二步 代表那张表的对象id
    object_id = models.PositiveIntegerField("绑定商品", null=True, blank=True)
    # 第三步 不会生成额外的列
    content_object = GenericForeignKey("content_type", "object_id")
View Code
class TestView(APIView):
    def get(self, request):
        # 给山东大馒头加优惠券
        food_obj = Food.objects.filter(id=1).first()
        # Coupon.objects.create(title="买一赠一", content_obj=food_obj)
        # 查看山东大馒头有哪些优惠券
        for coupon in food_obj.coupons.all():
            print(coupon.title)
        # 查看优惠券绑定的商品
        coupon_obj = Coupon.objects.first()
        print(coupon_obj.content_obj.title)

        return Response("ok")
测试views.py

 

posted @ 2018-11-08 21:05  猴里吧唧  阅读(174)  评论(0)    收藏  举报