django -- ContentType
前戏
假设现在我们有很多张表,比如Food表,Fruit表等等。有一天这些东西都要打折,那我们要新建一张表,里面写的打折信息,要把所有的表都关联在一起,这样的话就会在一张表里有很多的外键,例如下面的。
from django.db import models class Food(models.Model): """ id name 1 麻婆豆腐 2 木耳炒牛肉 3 西红柿炒鸡蛋 """ 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 title food_id fruit_id .......... 1 麻婆豆腐买一送一 1 null 2 香蕉2折 null 2 """ title = models.CharField(max_length=32) food = models.ForeignKey(to="Food") fruit = models.ForeignKey(to="Fruit")
优化表结构
既然一张表里有这么多的外键,那我们可不可以新建一张表,专门用来存放app和表名的,如下
from django.db import models class Food(models.Model): """ id name 1 麻婆豆腐 2 木耳炒牛肉 3 西红柿炒鸡蛋 """ 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 title food_id fruit_id .......... 1 麻婆豆腐买一送一 1 null 2 香蕉2折 null 2 """ title = models.CharField(max_length=32) table = models.ForeignKey(to="MyTables") object_id = models.IntegerField()
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)
Mytables表里存放了我们所有的app名和表名,在Coupon表里通过外键关系关联到MyTables表,这样就解决了一张表里多个外键的问题
ContentType
Django在生成数据表的时候已经给我们提供了这张表“MyTables”,表名叫content_type,里面的字段含义和我们自定义的一样
所以第三张表就不用我们自己创建了,直接使用Django自带的就可以了
from django.db import models from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation class Food(models.Model): name = models.CharField(max_length=32) # 不生成字段只用于反向查询 coupons = GenericRelation(to="Coupon") class Fruit(models.Model): name = models.CharField(max_length=32) coupons = GenericRelation(to="Coupon") class Coupon(models.Model): title = models.CharField(max_length=32) content_type = models.ForeignKey(to=ContentType) object_id = models.IntegerField() # 不会生成字段 只用于关联到对象的 content_object = GenericForeignKey("content_type", "object_id")
使用ORM添加数据
from django.shortcuts import render from rest_framework.views import APIView from django.http import HttpResponse from .models import Food, Fruit, Coupon from django.contrib.contenttypes.models import ContentType class TestView(APIView): def get(self, request): # 找到表id以及表对象 food_obj = Food.objects.filter(id=1).first() # 往Coupon表里插数据 Coupon.objects.create(title="水密桃大甩卖", content_object=food_obj) return HttpResponse("ok")
查询数据
from django.shortcuts import render from rest_framework.views import APIView from django.http import HttpResponse from .models import Food, Fruit, Coupon from django.contrib.contenttypes.models import ContentType class TestView(APIView): def get(self, request): # 查询出来的是Food或者Fruit对象 coupon_obj = Coupon.objects.filter(id=1).first() # 通过content_object.name拿到对应的name值 print(coupon_obj.content_object.name) # 查某个对象的优惠券 food_obj = Food.objects.filter(id=1).first() print(food_obj.coupons.all()) return HttpResponse("ok")
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)