13.ContentType组件
1.问题:一张表上如何对多个表进行外键关联
from django.db import models
class Appliance(models.Model):
"""
家用电器表
id name
1 冰箱
2 电视
3 洗衣机
"""
name = models.CharField(max_length=64)
class Food(models.Model):
"""
食物表
id name
1 面包
2 牛奶
"""
name = models.CharField(max_length=32)
class Fruit(models.Model):
"""
水果表
id name
1 苹果
2 香蕉
"""
name = models.CharField(max_length=32)
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", null=True, blank=True)
food = models.ForeignKey(to="Food", null=True, blank=True)
fruit = models.ForeignKey(to="Fruit", null=True, blank=True)
注意
1.每增加一张表就需要多增加一个字段,
2.定义:ContentTypes组件
ContentTypes是Django内置的一个组件
可以追踪项目中所有app和model的对应关系,并记录在ContentType表中
当一张表要跟多张表进行外键关联的时候,我们可以使用Django提供的ContentType 组件
app1/models.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
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)
# 不会生成coupons字段,只用于反向查询
coupons = GenericRelation(to="Coupon")
class Fruit(models.Model):
"""
id title
1 苹果
2 香蕉
"""
title = models.CharField(max_length=32)
class Coupon(models.Model):
title = models.CharField(max_length=32)
# 第一步:在 model中定义ForeignKey字段,并关联到ContentType表
content_type = models.ForeignKey(to=ContentType, null=True, blank=True, on_delete=models.SET_NULL)
# 第二步:定义IntegerField字段,用来存储关联表中的主键
object_id = models.IntegerField()
# 第三步 不会生成字段传入上面两个字段的名字
content_object = GenericForeignKey("content_type", "object_id")
django_content_type表
app1_coupon表
food表
app1\view.py
from django.contrib.contenttypes.models import ContentType
from django.http import HttpResponse
from django.views import View
from app1.models import Food, Coupon
class DemoView(View):
def get(self, request):
# 1.通过ContentType表找表模型
content = ContentType.objects.filter(app_label="app1", model="food").first()
content.get_object_for_this_type(id=1)
# 2.获得表model对象 相当于models.app1
model_class = content.model_class()
print(model_class.objects.all())
# 给面包创建一个优惠券
food_obj = Food.objects.get(id=1)
# 方式一
Coupon.objects.create(title="面包九五折", content_type_id=8, object_id=1)
# 方式二
t = Coupon(title="双十一面包九折促销", content_object=food_obj)
t.save()
# 正向查询:根据优惠信息查询优惠对象
coupon_obj = Coupon.objects.get(id=1)
print(coupon_obj.content_object.title)
# 反向查询:查询面包都有哪些优惠券
food_obj = Food.objects.filter(id=1).first()
coupons = food_obj.coupons.all()
print(coupons[0].title)
# 如果没定义反向查询
food_obj = Food.objects.filter(id=1).first()
food_type = ContentType.objects.get_for_model(Food)
result = Coupon.objects.filter(content_type=food_type, object_id=food_obj.id).all()
print(result[0].title)
return HttpResponse("ContentType测试")
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix