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字段
代码如下:models.py
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
# Create your models here.
class Food(models.Model):
"""
id name
1 酱香饼
2 鸡蛋饼
3 水煎包
"""
name = models.CharField(max_length=32)
# 不生成字段只用于反向查询
coupons = GenericRelation(to='Coupon')
class Fruit(models.Model):
"""
id name
1 红心蜜柚
2 黑美人西瓜
"""
name = models.CharField(max_length=32)
# 不生成字段只用于反向查询
coupons = GenericRelation(to='Coupon')
class Coupon(models.Model):
"""
id title food_id fruit_id
1 酱香饼买一送一 1 null
2 黑美人西瓜2折 null 2
id title table_id obj_id
1 酱香饼买一送一 1 1
2 黑美人西瓜2折 2 2
"""
title = models.CharField(max_length=32)
# 第一版设计
# food = models.ForeignKey(to='Food')
# fruit = models.ForeignKey(to='Fruit')
# 第二版设计
# table = models.ForeignKey(to='MyTables')
# object_id = models.IntegerField()
# 第三版设计
# ContentType 可以连接多个外键
content_type = models.ForeignKey(to=ContentType)
object_id = models.IntegerField()
# 不会生成字段 只用于关联类对象的
content_object = GenericForeignKey('content_type', 'object_id')
class MyTables(models.Model):
"""
id app_name table_name
1 Demo Food
2 Demo Fruit
"""
app_name = models.CharField(max_length=32)
table_name = models.CharField(max_length=32)
数据迁移后~添加数据~我们看下增删改查的操作~~
基本的使用
from django.shortcuts import render
# Create your views here.
from rest_framework.views import APIView
from django.http import HttpResponse
from .models import *
from django.contrib.contenttypes.models import ContentType
class TestView(APIView):
def get(self, request):
# 找到表的ID以及表对象
# content_type_obj = ContentType.objects.filter(app_label='Demo', model='food').first()
# print(content_type_obj, type(content_type_obj)) # food <class 'django.contrib.contenttypes.models.ContentType'>
# model_class = content_type_obj.model_class()
# print(model_class) # <class 'Demo.models.Food'>
# print(content_type_obj.pk) # 8
# 给酱香饼创建优惠券
food_obj = Food.objects.filter(id=1).first()
Coupon.objects.create(title='酱香饼买一送一', content_object=food_obj)
# 给黑美人加优惠券
fruit_obj = Fruit.objects.get(id=2)
Coupon.objects.create(title='黑美人2折', content_type_id=9, object_id=2)
# 查询优惠券绑定对象
coupon_obj = Coupon.objects.filter(id=1).first()
print(coupon_obj.content_object) # Food object
print(coupon_obj.content_object.name) # 酱香饼
# 查某个对象的优惠券
food_obj = Food.objects.filter(id=1).first()
print(
food_obj.coupons.all()) # <QuerySet [<Coupon: Coupon object>, <Coupon: Coupon object>, <Coupon: Coupon object>, <Coupon: Coupon object>]>
return HttpResponse('ok')