django ContentType組件
阿新 • • 發佈:2018-09-25
幫我 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組件