京西商城——商品相关接口开发

文章目录

  • 接口开发
    • django原生CBV开发==商品分类菜单==接口
    • 继承APIView开发==商品类型分类==接口
    • 通过序列化器开发==商品详情==接口

接口开发

django原生CBV开发商品分类菜单接口

先直接给出最终的views类,先简单的解释一下:

在基于CBV(基于类视图的)的接口时,直接在类中定义名字于请求名相等的方法即可

get请求中需要先获取符合条件的数据库中的数据

result_json = {‘status’: 1000, ‘data’: []} 是先定义一个返回的格式,‘status’: 1000是这个接口的响应码,通过循环将数据库中的数据会放在data中

最后返回一个HttpResponse响应,一定要清楚接口最后返回的是JSON数据,所以在返回Http响应响应时一定要用json.dumps函数将数据转化成JSON。

在代码中的for循环中,我一共打印了三组数据,反别是item,item.to_dict,result_json。他们的类型分别是对象,字典,字典。那么to_dict函数的意义又是什么呢?因为json.dumps函数不可以直接将自定义对象转换为JSON数据,所以需要在每一个model中定义一个方法(to_dict方法)将对象先转化为字典的形式。再通过json.dumps再返回时转化为JSON。

一级菜单接口和二级菜单接口:

menu/views.py
import json
from django.http import HttpResponse
from django.views import View
from apps.menu.models import MainMenu, SubMenu
from utils import ResponseMessageclass MainMenuView(View):def get(self, request):main_menu = MainMenu.objects.all()result_json = {'status': 1000, 'data': []}for item in main_menu:# print(item)  # item是对象 MainMenu object (1)  MainMenu object (2)  MainMenu object (3) MainMenu object (4)........# print(item.to_dict())  # {'main_menu_id': 1, 'main_menu_name': '家用电器'}{'main_menu_id': 2, 'main_menu_name': '手机'}{'main_menu_id': 2, 'main_menu_name': '运营商'}result_json['data'].append(item.to_dict())   #要通过每个item对象里的to_dict方法序列化对象# print(result_json)  # 字典,并不是JSON格式的数据return HttpResponse(json.dumps(result_json), content_type='application/json')# json.drup()将字典转化为JSON,content_type='application/json'告诉客户端这个响应是JSON格式的数据,客户端应该相应地处理它。class SubMenuView(View):def get(self, request):# 获取请求的参数param_id = request.GET['main_menu_id']sub_menu = SubMenu.objects.filter(main_menu_id=param_id)# 封装一个同意接受数据返回请求的方法return ResponseMessage.MenuResponse.success(sub_menu)

在模型类中添加to_dict方法:

menu/models.py
import jsonfrom django.db import modelsclass MainMenu(models.Model):main_menu_id = models.IntegerField(verbose_name='菜单ID')main_menu_name = models.CharField(max_length=255, verbose_name='菜单名称', null=False)main_menu_url = models.CharField(max_length=255, null=True, blank=True, verbose_name='菜单地址')# 手动序列化def to_dict(self):return {'main_menu_id': self.main_menu_id,'main_menu_name': self.main_menu_name,}class Meta:db_table = 'main_menu'class SubMenu(models.Model):main_menu_id = models.IntegerField( null=True, blank=True, verbose_name='一级菜单ID')submenu_id = models.IntegerField( null=True, blank=True, verbose_name='二级菜单ID')submenu_name = models.CharField(max_length=255, verbose_name='二级菜单名称', null=False)submenu_type = models.CharField(max_length=255, null=True, blank=True, verbose_name='二级菜单类型')submenu_url = models.CharField(max_length=255, null=True, blank=True, verbose_name='二级菜单地址')def to_dict(self):return{'main_menu_id': self.main_menu_id,'submenu_id': self.submenu_id,'submenu_name': self.submenu_name,'submenu_type': self.submenu_type,'submenu_url': self.submenu_url,}class Meta:db_table = 'sub_menu'

因为在写每一个接口时,数据返回逻辑就是每一个接口都要序列化然后转化为JSON,所以干脆创建一个工具类,用来让每一个接口直接调用这个工具类。

utils/ResponseMessage.py
from django.http import HttpResponse#分类菜单
class MenuResponse():@staticmethoddef success(data):result_json = {'status': '1000', 'data': []}for item in data:result_json['data'].append(item.to_dict())return HttpResponse(json.dumps(result_json), content_type='application/json')@staticmethoddef failed(data):result_json = {'status': '1001', 'data': []}for item in data:result_json['data'].append(item.to_dict())return HttpResponse(json.dumps(result_json), content_type='application/json')@staticmethoddef other(data):result_json = {'status': '1002', 'data': []}for item in data:result_json['data'].append(item.to_dict())return HttpResponse(json.dumps(result_json), content_type='application/json')

继承APIView开发商品类型分类接口

这个接口中基于APIView的接口开发和基于View的开发没有任何区别,因为在面向对象中APIView本身就是继承于View的,所以继承APIView会先在APIView找,如果APIView没有封装该方法,那么才会执行View中的方法

from rest_framework.views import APIView
from apps.goods.models import Goods
from utils import ResponseMessage# http://localhost:8000/goods/category_id/page
class GoodsCategoryAPIView(APIView):def get(self, request, category_id, page):current_page = (page - 1) * 20  #当前页的起始位置end_page = page * 20  #当前页的结束位置category_data = Goods.objects.filter(type_id=category_id)[current_page:end_page]return ResponseMessage.GoodsResponse.success(category_data)

这个时候要在ResponseMessage.py中加入商品分类的工具类,当然不能忘记在goods/models类中加入to_dict进行手动系列化:

import decimal
import json
from django.http import HttpResponse# 商品分类
class GoodsResponse():@staticmethoddef success(data):result_json = {'status': '2000', 'data': []}for item in data:result_json['data'].append(item.to_dict())return HttpResponse(json.dumps(result_json, cls=DecimalEncoder), content_type='application/json')@staticmethoddef failed(data):result_json = {'status': '2001', 'data': []}for item in data:result_json['data'].append(item.to_dict())return HttpResponse(json.dumps(result_json, cls=DecimalEncoder), content_type='application/json')@staticmethoddef other(data):result_json = {'status': '2002', 'data': []}for item in data:result_json['data'].append(item.to_dict())return HttpResponse(json.dumps(result_json, cls=DecimalEncoder), content_type='application/json')class DecimalEncoder(json.JSONEncoder):def default(self, obj):if isinstance(obj, decimal.Decimal):return float(obj)

这个编码器类用于处理 JSON 序列化过程中的Decimal 类型,json模块不能处理这种类型。通过指定 cls 参数,你可以确保所有的 Decimal 对象都被正确地转换为 JSON 字符串

通过序列化器开发商品详情接口

在使用序列化器之前,我们先用手动序列化的方式来实现商品详情接口:

goods/views
# http://localhost:8000/goods/sku_id
class GoodsDetailAPIView(APIView):def get(self, request, sku_id):good = Goods.objects.filter(sku_id=sku_id)return ResponseMessage.GoodsResponse.success(good)

因为商品详情是根据商品属性中的sku_id查找的,再此前的数据库设计的时候我没有添加这个属性,所以现在要添加这个属性

    sku_id = models.IntegerField(unique=True,null=False, verbose_name="sku_id")
python manage.py makemigrations      python manage.py migrate

使用序列化器:

使用序列化器要现创建一个继承自 serializers.ModelSerializer 的类,一般在app下创建一个serializers.py。

# goods/serializers.py
from rest_framework import serializers
from apps.goods.models import Goods
from jingxi_shop_project.settings import IMAGE_URLclass GoodsSerializer(serializers.ModelSerializer):# SerializerMethodField方法允许你为序列化器定义一个名为 get_属性 的方法,这个方法返回的值将作为该字段的值在序列化时输出photo_URL = serializers.SerializerMethodField()def get_photo_URL(self, obj):return IMAGE_URL + obj.photo_URLclass Meta:model = Goods # 指定了序列化器将要序列化的模型类是Goodsfields = "__all__" # 序列化器将包含模型定义的所有字段
# goods/views.py
# http://localhost:8000/goods/sku_id
class GoodsDetailAPIView(APIView):def get(self, request, sku_id):# good_data = Goods.objects.filter(sku_id=sku_id)  # 返回的是一个QuerySet查询集,并不是一个对象,哪怕符合条件的只有一个对象。good_data = Goods.objects.filter(sku_id=sku_id).first()  # 获取 QuerySet 中的第一个模型实例,是一个对象# 序列化的参数是instance,反序列化的参数是dataresult = GoodsSerializer(instance=good_data)result_json = {'status': '2000', 'data': result.data}return HttpResponse(json.dumps(result_json), content_type='application/json')

此时我们就可以通过sku_id来获取JSON格式的数据了:

在这里插入图片描述

特殊处理的字段会在最前面。
在上面我们用first()函数拿到了QuerySet查询集中的第一个实例,实际上还有另一种写法

  def get(self, request, sku_id):good_data = Goods.objects.filter(sku_id=sku_id)print(type(good_data))# 设置 many=True 表示告诉序列化器要处理多个对象也就是传入的instance是一个包含多个对象的查询集,通常用于处理查询集(QuerySet)返回的结果result = GoodsSerializer(instance=good_data, many=True)result_json = {'status': '2000', 'data': result.data}return HttpResponse(json.dumps(result_json), content_type='application/json')

直接用many=True告诉序列化器你要处理一个包含多个对象的查询集,他就会自己遍历并序列化了。


如果不特殊处理photo_URL这个字段,就会输出数据库中最原始的数据:

# goods/serializers.py
from rest_framework import serializers
from apps.goods.models import Goods
from jingxi_shop_project.settings import IMAGE_URLclass GoodsSerializer(serializers.ModelSerializer):class Meta:model = Goodsfields = "__all__"
# goods/views.py
class GoodsDetailAPIView(APIView):def get(self, request, sku_id):good_data = Goods.objects.filter(sku_id=sku_id)result = GoodsSerializer(instance=good_data)result_json = {'status': '2000', 'data': result.data}return HttpResponse(json.dumps(result_json), content_type='application/json')

在这里插入图片描述

若有错误与不足请指出,关注DPT一起进步吧!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/781955.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二维数组定义 求和,最值,求平均值 JS

定义二维数组 二维数组的求和,最值,求平均值 Eg1 // 二维数组 const matrix [[1, 2, 3],[4, 5, 6],[7, 8, 9] ];// 初始化求和、最大值和最小值 let sum 0; let max Number.MIN_VALUE; let min Number.MAX_VALUE;// 遍历二维数组 for (let i 0; i…

基于SSM的戒烟网站(有报告)。Javaee项目。ssm项目。

演示视频: 基于SSM的戒烟网站(有报告)。Javaee项目。ssm项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Spring SpringMv…

c++20中的jthread再谈

一、介绍 在前面的C20新功能中,简单的介绍过相关的std::jthread的应用。当时觉得它虽然比std::thread方便一些,但也没有多大的优势。可在后面的不断的学习中,发现std::jthread的使用上确实有优秀之处,相对于传统的线程编程&#…

大数据学习-2024/3/30-MySQL基本语法使用介绍实例

学生信息表 create table studend(stu_id int primary key auto_increment comment 学生学号,stu_name varchar(20) not null comment 学生名字,mobile char(11) unique comment 手机号码,stu_sex char(3) default 男 comment 学生性别,birth date comment 出生日期,stu_time …

《操作系统导论》第15章读书笔记:机制:地址转换(address translation)

《操作系统导论》第15章读书笔记:机制:地址转换(address translation) —— 杭州 2024-03-30 夜 文章目录 《操作系统导论》第15章读书笔记:机制:地址转换(address translation)1.前…

正点原子imx6ull-mini不使用网络更新内核系统

参考视频:【【正点原子】Linux网络环境搭建篇】 参考文档:从正点原子官方下载 这几天在学imx6ull写网络驱动检测出网卡,但是一直ping不通ubuntu,电脑还有ubuntu、开发板都处于同一个网段,跟着正点原子的视频试了双网…

新一代信息技术元年汇总

元年汇总: 大数据 1998 区块链 2008 云计算 2012 RPA 2018 移动通信技术(5G的元年) 2019

DW1000 定位技术解析

Qorvo 的 DW1000 是一款完全集成的单芯片超宽带 (UWB) 低功耗、低成本收发器 IC,符合 IEEE 802.15.4a 标准。它可用于 2 向测距或 TDoA 定位系统,以 10 厘米的精度定位资产。它还支持速率高达 6.8 Mbps 的数据传输。DW1000 由一个包含一个接收器137和一个…

flutter Got socket error trying to find package nested at

flutter Got socket error trying to find package nested at xxx 报错信息:“Got socket error trying to find package nested at” 通常出现在Flutter尝试从pub.dev获取依赖包时,由于网络问题导致无法连接到pub.dev或者无法正确解析包的路径。 例如&…

2_1.Linux中的网络配置

#1.什么是IP ADDRESS# internet protocol ADDRESS ##网络进程地址 ipv4 internet protocol version 4 ip是由32个01组成 11111110.11111110.11111110.11111110 254.254.254.254 #2.子网掩码# 用来划分网络区域 子网掩码非0的位对应的ip上的数字表示这个ip的网络位 子网掩码0位…

S7-1500PLC与ABB机器人RobotStudio调试演示

(1)建立空工作站 (2)选择机器人、导入吸盘、托盘、传送带 (3) 将导入的吸盘变为工具 (4)创建机器人系统 布局如下 (5)创建物体 (6)设置物体本地原点 (7)创建传送带Smart组件

单例设计模式(2)

单例设计模式(2) 单例模式存在的问题 单例对 OOP 特性的支持不友好 oop的特性:封装、继承、多态、抽象;以Id生成器代码为例,如果未来某一天,我们希望针对不同的业务采用不同的 ID 生成算法。比如&#x…

通过多选按钮选择需要修改什么字段

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、代码 前言 想要更新什么字段就将该字段更新,第一想到通过多选框控制,通过一系列的尝试,做了如下的布局和功能 直接上代…

[操作系统课设]GeeKOS操作系统的研究与实现

一.GeekOS操作系统概论 1.1教学操作系统 (1)针对RISC结构MIPS处理器 操作系统:Nachos、OS/161 (2)针对CISC结构Intel IA-32 (or x86)通用处理 操作系统:MINIX、GeekOS 我们用到的是:GeekOS 1&…

二分(二段性)

本文用于记录个人算法竞赛学习,仅供参考 一.二分算法 二分算法一般用于具有二段性的问题,数据不一定具有单调性,所以单调可二分,可二分不一定就要单调。 二.整数二分 1. 模板一:将区间[l, r]划分为[l, mid] 和 [mid…

字符串(KMP)

P3375 【模板】KMP - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; #define ll long long const int N1e6100; int n0,m; char s1[N]; char s2[N];…

36.HarmonyOS鸿蒙系统 App(ArkUI) 创建第一个应用程序hello world

36.HarmonyOS App(ArkUI) 创建第一个应用程序helloworld 线性布局 1.鸿蒙应用程序开发app_hap开发环境搭建 3.DevEco Studio安装鸿蒙手机app本地模拟器 打开DevEco Studio,点击文件-》新建 双击打开index.ets 复制如下代码&#xff1a; import FaultLogger from ohos.fau…

通俗易懂Redis缓存穿透,缓存击穿,缓存雪崩

1.1 缓存穿透 原因&#xff1a;当我们查询一个数据的时候&#xff0c;缓存中没有&#xff0c;就会去查询我们的关系型数据库&#xff0c;而且查询不到的数据是不会放到我们的缓存中&#xff0c;就会导致我们每次的请求都会来到我们的关系型数据库中&#xff0c;从而导致关系型…

代码随想录刷题day39|不同路径不同路径II

文章目录 day39学习内容一、不同路径2.1、动态规划五部曲1.1.1、 确定dp数组&#xff08;dp table&#xff09;以及下标的含义1.1.2、确定递推公式1.1.3、 dp数组如何初始化1.1.4、确定遍历顺序1.1.5、计算并返回最终结果 1.2、代码 二、不同路径II2.1、动态规划五部曲2.1.1、 …

使用Flink实现Kafka到MySQL的数据流转换:一个基于Flink的实践指南

使用Flink实现Kafka到MySQL的数据流转换 在现代数据处理架构中&#xff0c;Kafka和MySQL是两种非常流行的技术。Kafka作为一个高吞吐量的分布式消息系统&#xff0c;常用于构建实时数据流管道。而MySQL则是广泛使用的关系型数据库&#xff0c;适用于存储和查询数据。在某些场景…