飞行的猪哼哼

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一:获取图片列表资源:

1:定义序列化器:

from rest_framework import serializers
from apps.goods.models import  SKUImage
class ImageSerializers(serializers.ModelSerializer):
    class Meta:
        model = SKUImage
        fields = ["id", "sku", "image"]

2:定义一个视图类:

from rest_framework.viewsets import ModelViewSet

from apps.goods.models import  SKUImage
from apps.meiduo_admin.paginations import MyPage
from apps.meiduo_admin.serializers.image_serializers import ImageSerializers


class ImageView(ModelViewSet):
    queryset = SKUImage.objects.all()
    serializer_class = ImageSerializers
    pagination_class = MyPage

3:路由:

 re_path(r'^skus/images/$', ImageView.as_view({"get": "list"})),

4:测试:图片和信息获取到了。
在这里插入图片描述

二:新增图片可选的SKU:

1:序列化器定义:

class SKUImageSerializers(serializers.ModelSerializer):
    class Meta:
        model = SKU
        fields =["id", "name"]

2:定义模型类:

class SKUImageView(ModelViewSet):
    queryset = SKU.objects.all()
    serializer_class = SKUImageSerializers

3:定义路由:

 # 新增图片可选的SKU
    re_path(r'^skus/simple/$', SKUImageView.as_view({"get": "list"})),

4:测试:
在这里插入图片描述

三:重写validate函数实现上传:

<一>: 分析:根据前端传值:传入sku的id,和image(图片–>多媒体),这是个反序列化新建资源的过程。假设能够成功。只需要路径增加:

    # 图片路由:
    re_path(r'^skus/images/$', ImageView.as_view({"get": "list", "post": "create"})),

我的序列化器能够完成校验的工作吗??假设前端传入的值是sku=32,经过序列化之后会变成什么呢??image图片序列化后又变成什么呢?

class ImageSerializers(serializers.ModelSerializer):
    class Meta:
        model = SKUImage
        fields = ["id", "sku", "image"]

答案:进行validate测试一下:image变成被封装成特殊的文件对象,sku由前端传来的id类型,变成了sku对象。
在这里插入图片描述
特殊注意的知识点:

class SKUImage(BaseModel):
    """SKU图片"""
    sku = models.ForeignKey(SKU, on_delete=models.CASCADE, verbose_name='sku')
    image = models.ImageField(verbose_name='图片')

    class Meta:
        db_table = 'tb_sku_image'

    def __str__(self):
        return '%s %s' % (self.sku.name, self.id)

对于这个模型类SKUImage,如果sku这个对象被赋值成一个文件对象的话,就会自动触发文件存储后端来完成,如果sku对象被赋值成一个字符串,那么就不会触发存储后端,而是将该字符串直接存入数据库中。

class ImageSerializers(serializers.ModelSerializer):
    class Meta:
        model = SKUImage
        fields = ["id", "sku", "image"]

    def validate(self, attrs):

        image_obj = attrs.get('image')  # 图片文件对象
        # (1)、在校验过程中,手动从文件对象中读取图片数据,上传fdfs
        conn = Fdfs_client('./meiduo_mall/settings/client.conf')
        res = conn.upload_by_buffer(image_obj.read())
        if res is None:
            raise serializers.ValidationError("fdfs上传失败!")
        # (2)、再把fdfs返回的文件标示(文件id)作为有效数据中image字段的值
        attrs['image'] = res['Remote file_id']

        return attrs

四:自定义文件存储后端实现图片的上传:

出现的问题:像上面的图片上传,只能作用在一个视图,但是如果想要实现只要上传图片都能进行,此时就需要文件存储后端。
1:先来查看项目一中的存储后端代码:前面项目只是拼接路径返回,open和save方法没有用到,此时,模型类image字段被赋值成对象的时候,自动就会调用我的FastDFSStorage存储后端的save方法,

# 1:自定义的文件存储后端要继承django默认的存储后端Storage
class FastDFSStorage(Storage):

    def _open(self, name, mode="rb" ):
        # 打开django本地文件
        pass

    def _save(self, name, img_obj, max_length=None):
        # 上传图片
        pass

    def url(self, name):
        # 返回"http://image.meiduo.site:8888/" + 图片在数据库中存储的地址
        return settings.FDFS_BASE_URL + name

save方法的参数:name:文件的名称,也就是图片保存到本地数据库中的名称(图片不存储在本地,所以用不到) img_obj: 传来的文件传来的文件对象,就是image对象被赋值后的对象,这个对象会被传递到存储后端来。注意:save返回值就是当前字段存储在mysql中的图片id。

from django.core.files.storage import Storage
from django.conf import settings


# 1:自定义的文件存储后端要继承django默认的存储后端Storage
from fdfs_client.client import Fdfs_client
from rest_framework import serializers


class FastDFSStorage(Storage):

    def _open(self, name, mode="rb" ):
        # 打开django本地文件
        pass

    def _save(self, name, image_obj, max_length=None):
        # 上传图片
        conn = Fdfs_client('./meiduo_mall/settings/client.conf')
        res = conn.upload_by_buffer(image_obj.read())
        if res is None:
            raise serializers.ValidationError('上传fdfs失败!')
        file_id = res['Remote file_id']

        # 注意:_save方法返回值就是当前字段,存储在mysql中的文件id
        return file_id

    def exists(self, name):
        # 功能:判断上传的文件在Django本地是否重复
        # True:表示重复
        # Fales:表示不重复
        return False

    def url(self, name):
        # 返回"http://image.meiduo.site:8888/" + 图片在数据库中存储的地址
        return settings.FDFS_BASE_URL + name



在这里插入图片描述

posted on 2020-09-30 15:44  飞行的猪哼哼  阅读(63)  评论(0)    收藏  举报