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

文章目录

  • 接口开发
    • 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…

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

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

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

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

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组件

[操作系统课设]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;从而导致关系型…

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

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

小米SU7 我劝你再等等

文 | AUTO芯球 作者 | 李逵 我必须承认我一时没忍住 犯错了 我不会被我老婆打吧 感觉有点慌呀 这不前两天 我刚提了台问界M9嘛 但是昨晚看小米汽车发布会 是真的被雷总感染到了 真的没忍住 我又冲了台小米SU7 Pro版 本来我是准备抢创始版的 结果1秒钟时间 点进去就…

yolov5 v7.0打包exe文件,使用C++调用

cd到yolo5文件夹下 pyinstaller -p 当前路径 -i logo图标 detect.py问题汇总 运行detect.exe找不到default.yaml 这个是yolov8里的文件 1 复制权重文件到exe所在目录。 2 根据报错提示的配置文件路径&#xff0c;把default.yaml复制放到相应的路径下。&#xff08;缺少相应…

杨辉三角形(c++实现)

题目 下面的图形是著名的杨辉三角形&#xff1a; 如果我们按从上到下、从左到右的顺序把所有数排成一列&#xff0c;可以得到如下数列&#xff1a; 1, 1, 1, 1, 2, 1, 1, 3, 3, 1, 1, 4, 6, 4, 1, … 给定一个正整数 N&#xff0c;请你输出数列中第一次出现 N 是在第几个数&a…

实现 Element UI el-table 树形数据的懒加载

当面对大量数据时&#xff0c;一次性加载所有数据可能会导致性能问题。为了解决这一问题&#xff0c;我们可以实现树形数据的懒加载。本文将介绍如何在使用 Element UI 的 Vue 应用中为 el-table 组件的树形数据添加懒加载功能。 懒加载的基本概念 懒加载是一种优化网页或应用…

中国31个省农村用电量(2000-2022年)

数据介绍&#xff1a; 农村用电量是一个动态变化的数据&#xff0c;受到多种因素的影响&#xff0c;包括农村经济发展、人口增长、农业生产活动增加以及电力设备的升级改造等。随着农村经济的发展和农民生活水平的提高&#xff0c;农村用电量呈现出逐年增长的趋势。同时&#…

消息中间件区别

ActiveMQ 我们先看ActiveMQ。其实一般早些的项目需要引入消息中间件&#xff0c;都是使用的这个MQ&#xff0c;但是现在用的确实不多了&#xff0c;说白了就是有些过时了。我们去它的官网看一看&#xff0c;你会发现官网已经不活跃了&#xff0c;好久才会更新一次。 它的单机吞…

查找某数据在单链表中出现的次数

#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> typedef int ElemType; typedef struct LinkNode {ElemType data;LinkNode* next; }LinkNode, * LinkList; //尾插法建立单链表 void creatLinkList(LinkList& L) {L (LinkNode*)mallo…