保存图片数据
在保存数据之前我们需要先获取图片关联的sku的id
1、获取sku表id
接口分析
请求方式: GET /meiduo_admin/skus/simple/
# -------获取sku的id--------url(r'skus/simple/$', images.ImageView.as_view({'get': 'simple'})),
请求参数: 通过请求头传递jwt token数据。
返回数据: JSON
[{"id": 1,"name": "Apple MacBook Pro 13.3英寸笔记本 银色"},{"id": 2,"name": "Apple MacBook Pro 13.3英寸笔记本 深灰色"},......]
返回值 | 类型 | 是否必须 | 说明 |
---|---|---|---|
Id | int | 是 | sku商品id |
name | 数组 | 是 | Sku商品名称 |
后端实现
from rest_framework.permissions import IsAdminUser
from rest_framework.viewsets import ModelViewSet
from meiduo_admin.serializers.images import ImageSeriazlier, SKUSeriazlier
from goods.models import SKUImage, SKU
from meiduo_admin.utils import UserPageNum
from rest_framework.response import Responseclass ImageView(ModelViewSet):# 图片序列化器serializer_class = ImageSeriazlier# 图片查询集queryset = SKUImage.objects.all()# 分页pagination_class = UserPageNumpermission_classes = [IsAdminUser]# 获取sku商品信息def simple(self, request):# 查询所有的sku商品data = SKU.objects.all()# 序列化操作返回ser = SKUSeriazlier(data, many=True)return Response(ser.data)
序列化器的定义
from goods.models import SKUclass SKUSeriazlier(serializers.ModelSerializer):class Meta:model=SKUfields=('id','name')
2、保存图片数据
接口分析
请求方式:POST /meiduo_admin/skus/images/
# 图片查询路由****************************
router = DefaultRouter()
router.register('skus/images', images.ImageView, base_name='images')
# print(router.urls)
urlpatterns += router.urls
请求参数: 通过请求头传递jwt token数据。
表单提交数据:"sku": "SKU商品id","image": "SKU商品图片"
参数 | 类型 | 是否必须 | 说明 |
---|---|---|---|
sku | str | 是 | SKU商品id |
image | Fiel | 是 | SKU商品图片 |
返回数据: JSON
{"id": "图片id","sku": "SKU商品id","image": "图片地址"}
参数 | 类型 | 是否必须 | 说明 |
---|---|---|---|
id | Int | 是 | 图片id |
sku | int | 是 | SKU商品id |
image | str | 是 | 图片地址 |
后端实现
在保存图片的同时,我们还需要异步生成新的详情页页面,这是我们需要定义异步任务
【后端人员修改图片后,执行静态页面更改图片时可能速度会慢一些,所以防止阻塞这儿要使用异步任务】
import os
from django.conf import settings
from django.shortcuts import renderfrom meiduo_mall.utils.categories import get_categories
from meiduo_mall.utils.breadcrumb import get_breadcrumb
from goods.models import SKU
from celery_tasks.main import app@app.task(name='get_detail_html')
def get_detail_html(sku_id):# 获取当前sku对象sku = SKU.objects.get(id=sku_id)# 分类数据categories = get_categories()# 获取面包屑导航breadcrumb = get_breadcrumb(sku.category)# 获取spuspu = sku.spu# 获取规格信息:sku===>spu==>specsspecs = spu.specs.order_by('id')# 查询所有的sku,如华为P10的所有库存商品skus = spu.skus.order_by('id')'''{选项:sku_id}说明:键的元组中,规格的索引是固定的示例数据如下:{(1,3):1,(2,3):2,(1,4):3,(2,4):4}'''sku_options = {}sku_option = []for sku1 in skus:infos = sku1.specs.order_by('spec_id')option_key = []for info in infos:option_key.append(info.option_id)# 获取当前商品的规格信息if sku.id == sku1.id:sku_option.append(info.option_id)sku_options[tuple(option_key)] = sku1.id# 遍历当前spu所有的规格specs_list = []for index, spec in enumerate(specs):option_list = []for option in spec.options.all():# 如果当前商品为蓝、64,则列表为[2,3]sku_option_temp = sku_option[:]# 替换对应索引的元素:规格的索引是固定的[1,3]sku_option_temp[index] = option.id# 为选项添加sku_id属性,用于在html中输出链接option.sku_id = sku_options.get(tuple(sku_option_temp), 0)# 添加选项对象option_list.append(option)# 为规格对象添加选项列表spec.option_list = option_list# 重新构造规格数据specs_list.append(spec)context = {'sku': sku,'categories': categories,'breadcrumb': breadcrumb,'category_id': sku.category_id,'spu': spu,'specs': specs_list}response = render(None, 'detail.html', context)file_name = os.path.join(settings.BASE_DIR, 'static/detail/%d.html' % sku.id)# 写文件with open(file_name, 'w') as f1:f1.write(response.content.decode())
视图代码
在settings中配置fastdfs文件路径:
# 指定fastdfs文件路径
FASTDFS_PATH = os.path.join(BASE_DIR, 'utils/fdfs/client.conf')
images.py
from rest_framework.permissions import IsAdminUser
from rest_framework.viewsets import ModelViewSet
from meiduo_admin.serializers.images import ImageSerializer, SKUSerializer
from goods.models import SKUImage, SKU
from meiduo_admin.utils import UserPageNum
from rest_framework.response import Response
from fdfs_client.client import Fdfs_client
from django.conf import settings
from celery_tasks.static_file.tasks import get_detail_htmlclass ImageView(ModelViewSet):# 图片序列化器serializer_class = ImageSerializer# 图片查询集queryset = SKUImage.objects.all()# 分页pagination_class = UserPageNum# permission_classes = [IsAdminUser]# 获取sku商品信息def simple(self, request):# 查询所有的sku商品data = SKU.objects.all()# 序列化操作返回ser = SKUSerializer(data, many=True)return Response(ser.data)# 重写拓展类的保存业务逻辑def create(self, request, *args, **kwargs):# 创建FastDFS连接对象client = Fdfs_client(settings.FASTDFS_PATH)# 获取前端传递的image文件data = request.FILES.get('image')# 上传图片到fastDFSres = client.upload_by_buffer(data.read())# 判断是否上传成功if res['Status'] != 'Upload successed.':return Response(status=403)# 获取上传后的路径image_url = res['Remote file_id']# 获取sku_idsku_id = request.data.get('sku')[0]# 保存图片img = SKUImage.objects.create(sku_id=sku_id, image=image_url)# 生成新的详情页页面get_detail_html.delay(img.sku.id)# 返回结果return Response({'id': img.id,'sku': sku_id,'image': img.image.url # 这儿返回是完整的路由信息},status=201 # 前端需要接受201状态)
【上面的create方法可以封装到序列化器中的,具体操作可以看源码。其实这些代码在序列化器中写好后,这些代码是可以直接注释掉的,父类方法中已经提供了这些操作。在序列化器中是没有request属性的,可以使用self.context['request']代替】
修改后的代码:
序列化器:【视图中的create代码可以都注释掉了】
from rest_framework import serializers
from goods.models import SKUImage
from goods.models import SKU
from rest_framework.response import Response
from fdfs_client.client import Fdfs_client
from django.conf import settings
from celery_tasks.static_file.tasks import get_detail_htmlclass ImageSerializer(serializers.ModelSerializer):# 返回图片关联的sku的id值sku = serializers.PrimaryKeyRelatedField(read_only=True)class Meta:model = SKUImage# fields = ('sku', 'image', 'id')fields = '__all__'def create(self, validated_data):# 创建FastDFS连接对象client = Fdfs_client(settings.FASTDFS_PATH)# 获取前端传来的image文件data = self.context['request'].FILES.get('image')# data = request.data# 上传图片到fastDFSres = client.upload_by_buffer(data.read())# 判断是否上传成功if res['Status'] != 'Upload successed.':return Response(status=403)# 获取上传后的路径image_url = res['Remote file_id']# 获取sku_idsku_id = self.context['request'].data.get('sku')[0]# 保存图片img = SKUImage.objects.create(sku_id=sku_id, image=image_url)# 异步生成详情页静态页面get_detail_html.delay(img.sku.id)return img
注意事项:这儿可能不能直接安装fdfs-client,这儿可以使用提前准备好的安装包文件,pip install fdfs-client-py-master.zip
关于FastDFS客户端上传文件以及安装各个注意事件,查看博文:
https://blog.csdn.net/weixin_44799217/article/details/118463124