1. 程式人生 > >django ContentType組件

django ContentType組件

幫我 fir rst creat 主鍵 關聯 test spa res

一,需求

給商品創建優惠券;

看看下面表結構:

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")

django ContentType組件