前后端分离djangorestframework——ContentType组件表
ContentType
ContentType其实django自带的,但是平时的话很少会用到,所以还是放在Djangorestframework这个部分
作用:
在实际的开发中,由于数据库量级大,所以数据库表也很多,外键关联也很多,比如下面这个例子,一个电商平台的数据库表:

除非是专项的电商平台,比如只卖手机那种,像那种类别太多的这样每有一个类别的数据库表,就要在优惠券表里做以下外键约束,假如有几十几百张数据库表呢?这就很不符合我们的开发规范了,所以可以自定义一个【中间表】

这其中什么关系呢?图示:

然而这个table中间表不需要我们手动定义,django自带了一个ContentType表,这个表的作用就等同于【table中间表】,在最开始学django时,迁移数据库时会自动创建一些数据库表,ContentType表就是其中一个:

在书写玩自己的model表后,迁移时就会把一些数据迁移到ContentType里:DRF是前面的实例用到的,可以忽略,testapp是我刚创建的,一会儿就要用到:

修改代码,绑定到ContentType表上,注意导入ContentType表,导入它自己的外键关联

迁移数据库表得:

基于ContentType的增伤改查
先添加一些数据:
food:

product3c:

coupon:

看到这个coupon的时候,其实发现了,刚才那个content_object其实不会生成字段,只是多了一个功能,这个功能一会儿再说

本次我们的重点就在coupon这张表上:
coupon的增:
一般方法添加:
为实物类的三只松鼠小吃添加优惠券,查看contentType表的food表的id:

food的三只松鼠小吃id:

好的,相关的代码:
url:

view:

访问页面:
查看coupon表:

发现这个方法还是不太好,我去,我添加优惠券还是要去数据库里看了id是多少才能添加,这不是很麻烦吗?
用GenericForeignKey添加:
此时的GenericForeignKey就是刚才那个在coupon表里定义了属性,但并没有生成字段的那个值——content_object:


访问测试:

创建成功
查询
正向查询:
优惠券的外键利用ContentType正向约束给商品表,所以利用优惠券查有哪些商品,
又用了content_object这个字段:

打开数据库验证,优惠券id为1对应的商品食物类的id确实3:

反向查询
利用商品对象查有哪些优惠券:
在这个之前,我们的商品表需要做如下调整:

数据库迁移之后,反向查询代码:

数据库验证:id为1的food表的coupon优惠券的id确实是2:

修改:
修改food表id为3的对应优惠券打折为5折:

访问测试:

查看数据库表:

删除:
数据库表目前是这样:


视图类:

访问网页:

查看数据库数据还在不在:


很简答吧?因为用了GenericRelation做关联,删除商品表时,优惠券表也跟着删除了,根据外键约束的on_delete,on_cascade一样
通过ContentType找数据库表对象:
这个功能以后可能会用到,其中app_label就是数据库里存的我们的app名称,model就是数据库表名,注意数据库表名必须是小写
通过model_class方法就可以反解出数据库表对象,然后这个对象就可以使用对应数据库表的相关操作了

相关代码:
url:
from django.contrib import admin
from django.urls import path, re_path, include
from testapp.views import TestView
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'test/',TestView.as_view()),
re_path(r'parser/', include(('DRF.urls'))),
]
model:
from django.db import models
# Create your models here.
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
class Food(models.Model):
"""食物"""
title = models.CharField(max_length=32, verbose_name='食物名')
price = models.FloatField()
coupons = GenericRelation(to='Coupon')
class Product3c(models.Model):
"""3c数码产品"""
title = models.CharField(max_length=32, verbose_name='数码产品名')
price = models.FloatField()
#
# """如果有很多类别的商品名,那么每个类别的商品表都要跟优惠券表做外键约束"""
#
#
# class Table(models.Model):
# """中间表"""
# app_name = models.CharField(max_length=32, verbose_name='app名称')
# model_name = models.CharField(max_length=32, verbose_name='表名')
#
#
# class Coupon(models.Model):
# """优惠券"""
# title = models.CharField(max_length=32, verbose_name='数码产品名')
# table = models.ForeignKey(to=Table,on_delete='cascade',verbose_name='数据库表名')
# objects = models.IntegerField(verbose_name='数据库表中某个对象')
#
class Coupon(models.Model):
"""优惠券"""
title = models.CharField(max_length=32, verbose_name='数码产品名')
# 做外键约束到ContentType表
content_type = models.ForeignKey(to=ContentType, on_delete='cascade', verbose_name='数据库表名')
object_id = models.IntegerField(verbose_name='数据库表中某个对象')
# 绑定字段关系,并不会生成字段
content_object = GenericForeignKey('content_type', 'object_id')
view:
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.views import Response
from testapp.models import Food, Coupon
from django.contrib.contenttypes.models import ContentType
# Create your views here.
class TestView(APIView):
def get(self, request):
# 增
# food = Food.objects.filter(id=1).first()
# Coupon.objects.create(title='三只松鼠小吃8折',content_type_id=9,object_id=3)
# Coupon.objects.create(title='张飞牛肉7折', content_object=food)
# 正查
# coupon = Coupon.objects.filter(id=1).first()
# product = coupon.content_object
# print(product)
# 反查
# coupon = food.coupons.all()
# print(coupon)
# 改(正向反向改都一样了,随意操作,这里只给出反向修改的,剩下的自己研究)
# food = Food.objects.filter(id=3).first()
# coupon = food.coupons.all().first()
# coupon.title = '大特价5折'
# coupon.save()
# 删
"""如果要反向删,找到food对应的coupn,利用表Coupon.delete(coupon)删除"""
# food = Food.objects.filter(id=1).first()
# coupon = food.coupons
# Coupon.delete(coupon)
"""促销活动已结束,id为3的食物已卖完,删除id为3的记录和对应的优惠券"""
Food.objects.filter(id=3).delete()
# 通过ContentType表找对应的数据库表对象
# content_type = ContentType.objects.filter(app_label='testapp', model='food').first()
# print('content_type:', content_type)
#
# model = content_type.model_class()
# print('model:', model)
#
# result = model.objects.all()
# print('result:', result)
return Response('content type 测试')
总结:
- 注意ContentType的用法,添加一个字段,添加约束关系,被约束的表添加一个链接关系
- ContentType表的作用就是减少数据表的外键关联字段,存的就是django的app及app下对应的数据库表名
- 利用ContentType的GenericForeignKey,将contentType字段和一个数据库表的对象的id联合约束一下,就是做中间层的外键关联,让ContentType去接管我们开发用的实际数据库表关系
- 需要通过ContentType反查对应的数据库表对象的话,用model_class方法
前后端分离djangorestframework——ContentType组件表的更多相关文章
- 前后端分离djangorestframework——路由组件
在文章前后端分离djangorestframework——视图组件 中,见识了DRF的视图组件强大,其实里面那个url也是可以自动生成的,就是这么屌 DefaultRouter urls文件作如下调整 ...
- 前后端分离djangorestframework——视图组件
CBV与FBV CBV之前说过就是在view.py里写视图类,在序列化时用过,FBV就是常用的视图函数,两者的功能都可以实现功能,但是在restful规范方面的话,CBV更方便,FBV还要用reque ...
- 前后端分离djangorestframework——分页组件
Pagination 为什么要分页也不用多说了,大家都懂,DRF也自带了分页组件 这次用 前后端分离djangorestframework——序列化与反序列化数据 文章里用到的数据,数据库用的my ...
- 前后端分离djangorestframework——认证组件
authentication 认证是干嘛的已经不需要多说.而前后端未分离的认证基本是用cookie或者session,前后端分离的一般用token 全局认证 先创建一个django项目,项目名为drf ...
- 前后端分离djangorestframework——权限组件
权限permissions 权限验证必须要在认证之后验证 权限组件也不用多说,读了源码你就很清楚了,跟认证组件很类似 具体的源码就不展示,自己去读吧,都在这里: 局部权限 设置model表,其中的ty ...
- 前后端分离djangorestframework—— 在线视频平台接入第三方加密防盗录视频
加密视频 在以后的开发项目中,很可能有做在线视频的,而在线视频就有个问题,因为在线播放,就很有可能视频数据被抓包,如果这个在线视频平台有付费视频的话,这样就会有人做点倒卖视频的生意了,针对这个问题,目 ...
- 前后端分离djangorestframework—— 接入第三方的验证码平台
关于验证码部分,在我这篇文章里说的挺详细的了:Python高级应用(3)—— 为你的项目添加验证码 这里还是再给一个前后端分离的实例,因为极验官网给的是用session作为验证的,而我们做前后端分离的 ...
- 前后端分离djangorestframework——序列化与反序列化数据
我们写好后端的代码,要把数据交给前端的展示的,这个数据以什么类型给前端呢?学到这里,我们已经知道这个数据最好是json字符串才行,因为网络间的传输,只认字符串或者二进制,字符串就是我们的数据,二进制就 ...
- 前后端分离djangorestframework——restful规范
restful现在非常流行,所以很有必要提一下 web服务交互 在浏览器中能看到的每个网站,都是一个web服务.那么我们在提供每个web服务的时候,都需要前后端交互,前后端交互就一定有一些实现方案,我 ...
随机推荐
- 【Spark篇】---Spark中内存管理和Shuffle参数调优
一.前述 Spark内存管理 Spark执行应用程序时,Spark集群会启动Driver和Executor两种JVM进程,Driver负责创建SparkContext上下文,提交任务,task的分发等 ...
- pytorch学习:准备自己的图片数据
图片数据一般有两种情况: 1.所有图片放在一个文件夹内,另外有一个txt文件显示标签. 2.不同类别的图片放在不同的文件夹内,文件夹就是图片的类别. 针对这两种不同的情况,数据集的准备也不相同,第一种 ...
- socket编程: TypeError: must be bytes or buffer, not str
先看一段代码 #!/usr/bin/env python3 from socket import * serverName = "10.10.10.132" serverPort ...
- Nginx学习系列三Nginx的启动、停止、修改配置文件后重启
1.启动Nginx 命令规则:Ngxin的安装地址 -c Nginx的安装地址下的配置文件地址 注意:一般都在root权限下进行Nginx的启动 2.停止Nginx (1).从容停止 第一步:查看Ng ...
- Spring系列之手写一个SpringMVC
目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 Spring系列之AOP的原理及手动实现 Spring系列之手写注解与配置文件的解析 引言 在前面的几个章节中我 ...
- 环境与工具2:建立高效的mac环境
你的工作与生活离不开电脑,电脑是一个工具,也是一个环境.环境是不是绿水青山,是不是得心应手,这是很重要的事情.小程平时使用macbook来学习跟娱乐,最近重装了系统,很多环境与工具都需要重新组建. 那 ...
- consistent hash(一致性哈希算法)
一.产生背景 今天咱不去长篇大论特别详细地讲解consistent hash,我争取用最轻松的方式告诉你consistent hash算法是什么,如果需要深入,Google一下~. 举个栗子吧: 比如 ...
- Lambda in Java VS in C#
核心+变化 “凡是钱能解决的问题,就不是大问题.有很多问题是钱无法解决的,比如生老病死,比如不再相爱.”,看过<蜗居>的朋友一眼就能认出来.虽然这部电视剧讲的是chugui,但是毫无违和感 ...
- 做了2个多月的设计和编码,我梳理了Flutter动态化的方案对比及最佳实现
背景 在端上为了提升App的灵活性, 快速解决万变的业务需求,开发者们探索了多种解决方案,如PhoneGap ,React Native ,Weex等,但在Flutter生态还没有好的解决方案.未来闲 ...
- Nginx的正向代理与反向代理详解
正向代理和反向代理的概念 代理服务(Proxy),通常也称为正向代理服务. 如果把局域网外Internet想象成一个巨大的资源库,那么资源就分布到了Internet的各个点上,局域网内的客户端要访问这 ...