测试开发实战-手把手系列之四-(后端)


  大家好,这里是<测试开发实战-手把手系列之四>

  在上一节中我们创建了product(产品)应用,讲这一节前我们先创建一个project(组件)应用,基本框架与product一致,过程不再详细说明。
在这里插入图片描述

  前面说过,项目的结构是1个product对应多个project,1个project有多个product使用,所以product和project的对应关系是多对多,这样就需要一个关联表product_project来保存他们的对应关系。

  我们创建一个ProductProject应用来专门处理他们之间的关联
在这里插入图片描述


看一下ProductProject应用的model.py

model.py

import ...
class ProductProjectModel(models.Model):
    id = models.IntegerField(primary_key=True, db_column='id')
    product_id = models.IntegerField(max_length=11)
    project_id = models.IntegerField(max_length=11)
    class Meta:
        db_table = "product_project"

  可以看到,上面的字段与数据库的字段是对应的,但与我们实际使用是不契合的。比如前端想展示product和project的对应关系并显示名称,根据上面model的结构,我只能得到是product_id和project_id
在这里插入图片描述

显然,这不是我想要的,我真正想要的是所有的product_id和project _id对应的product和project对象,这里,就用到了外键(ForeignKey)这个东西。


我们改造一下
model.py改

from django.db import models
from product.model import productModel
from project.models import projectModel
class ProductProjectModel(models.Model):
    id = models.IntegerField(primary_key=True, db_column='id')
    product_id = models.IntegerField
    project_id = models.IntegerField
    project = models.ForeignKey(projectModel, related_name='ProductProject_project', on_delete=models.CASCADE)  # 关联外键
    product = models.ForeignKey(productModel, related_name='ProductProject_product', on_delete=models.CASCADE)  # 关联外键
    class Meta:
        db_table = "product_project"

重点
1、ForeignKey:外键关键字

2、related_name:子表在主表中对应的外键属性,需保证唯一性

3、on_delete: 删除关联表(project)中的数据时,当前表(ProductProject)与其关联的field的行为

  这样我们就把project用外键关联起来了,我们调一下ProductProject.SelectAll接口
在这里插入图片描述

  呵呵,没起作用,查看SelectAll代码,发现使用的是object.values()方法

#查询所有
class SelectAll(View):
    def post(self, request):
        listRes = ProductProjectModel.objects.values()
        listRes = list(listRes)
        return HttpResponse(json.dumps({"modelList": listRes, "code": 20000}, cls=DateEncoder),
                            content_type="application/json")

改成all()方法,调接口,结果报错了

TypeError: Object of type ProductProjectModel is not JSON serializable
提示对象类型不能json序列化

object.values()和object.all()的区别请参考上一节


  OK,到了这里,就来到本节重头了,为了解决这个问题我们使用django的REST framework模块

  不多说,pip安装djangorestframework后,配置setting文件,加入rest_framework应用

  我们新建一个rest_searilizers文件,专门处理对象序列化
在这里插入图片描述

rest_searilizers.py内容如下

from rest_framework import serializers #导入序列化模块
from product.model import productModel
from project.models import projectModel
from ProductProject.models import ProductProjectModel

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = productModel# 序列化的模型
        fields = '__all__'# fields 属性设置为特殊值 '__all__', 实例化时将可以看到所有字段

class ProjectSerializer(serializers.ModelSerializer):
    class Meta:
        model = projectModel
        fields = '__all__'

class ProductProjectSerializer(serializers.ModelSerializer):
    project = ProjectSerializer(read_only=True)# 外键关联的对象并设置read_only=True
    product = ProductSerializer(read_only=True)
    class Meta:
        model = ProductProjectModel
        fields = '__all__'

是不是很简单,以上代码就将product和project与ProductProject通过外键id进行了关联

我们优化下SelectAll接口

# 查询所有
class SelectAll(View):
    def post(self, request):
        listRes = ProductProjectModel.objects.all()
        listRes = rest_searilizers.ProductProjectSerializer(listRes, many=True) #注意这里,修改了
        data_set = json.dumps(listRes.data, cls=DateEncoder)
        data_set = json.loads(data_set)
        return HttpResponse(json.dumps({"modelList": data_set, "code": 20000}, cls=DateEncoder),
                            content_type="application/json")

然后我们再调下ProductProject.SelectAll接口
在这里插入图片描述

可以看到结果已经是我想要的。


  好了,现在前端又有个需求,我还想知道某个project的对应情况,即根据project的name进行查询。我们知道在ProductProject的表中,是没有name这个字段的,那怎么搞??

  解决的办法有不少,比如我先根据name查出所有的project_id,再根据project_id查询对应关系等等

  这里我们有个简单的方法,查出所有对象,然后根据外键的project对象数据进行筛选,代码如下

#根据条件查询
class SelectBySelective(View):
    def post(self, request):
        recordList = ProductProjectModel.objects.all()
        dto = json.loads(request.body)
        if dto.get('id'):
            recordList = recordList.filter(id=dto.get('id'))
        if dto.get('project_id'):
            recordList = recordList.filter(project_id=dto.get('project_id'))
        if dto.get('product_id'):
            recordList = recordList.filter(product_id=dto.get('product_id'))
        if dto.get('projectName'):
            search = dto.get('projectName')
            recordList = recordList.filter(project__name__icontains=search) #根据外键查出的project的name进行筛选
        listRes = rest_searilizers.ProductProjectSerializer(recordList, many=True) #序列化查询结果
        data_set = json.dumps(listRes.data)
        data_set = json.loads(data_set)
        return HttpResponse(json.dumps({"modelList": data_set, "code": 20000}),
                            content_type="application/json")

重点
1、filter()方法,对数据进行筛选

2、project__name__icontains:对数据的project对象的name进行模糊查询


总结

  在开发中,我们会经常遇到对象之间有关联的情况,都可以通过外键进行关联,然后在输出时对数据进行序列化,返回给前端。

演示代码:
https://github.com/danzi516/TestDev/tree/main/%E6%89%8B%E6%8A%8A%E6%89%8B/4/myproject


更多文章,关注一波,谢!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值