博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前后端分离djangorestframework——ContentType组件表
阅读量:6484 次
发布时间:2019-06-23

本文共 4932 字,大约阅读时间需要 16 分钟。

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 adminfrom django.urls import path, re_path, includefrom testapp.views import TestViewurlpatterns = [    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 ContentTypefrom django.contrib.contenttypes.fields import GenericForeignKey, GenericRelationclass 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 renderfrom rest_framework.views import APIViewfrom rest_framework.views import Responsefrom testapp.models import Food, Couponfrom 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方法

转载于:https://www.cnblogs.com/yangva/p/10428744.html

你可能感兴趣的文章
TextBox客户端JS赋值 后台获取(转载)
查看>>
PCA误差
查看>>
烦人的数据不一致问题到底怎么解决?——通过“共识”达成数据一致性
查看>>
抽象类详解
查看>>
《Oracle高性能自动化运维》一一2.2 队列锁(Enqueue Lock)
查看>>
《jQuery Mobile入门经典》—— 2.3 使用JavaScript完成功能
查看>>
java.lang.UnsupportedOperationException的解决方法
查看>>
让Erlang服务器后台运行
查看>>
APUE笔记七
查看>>
天兔监控安装
查看>>
python笔记-正则表达式
查看>>
Java二进制指令代码解析
查看>>
我的Python学习记录
查看>>
quzatz --Could not load org.quartz.spi.Trigge...
查看>>
qml实现窗口的拖拽效果
查看>>
Centos安装Mysql
查看>>
android Looper 非UI线程中更新UI
查看>>
js if语句多个条件判断
查看>>
AVPacketList结构体和AVPacketQueue结构体
查看>>
PHP操作redis详细讲解
查看>>