You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django REST Framework图片上传Swagger无选择文件按钮问题

Django REST Framework 图片上传接口Swagger无文件选择按钮问题

问题描述

使用Django REST Framework实现Office图片上传接口,已配置MEDIA_URL和MEDIA_ROOT,但在Swagger访问/office/office/{id}/upload-image/接口时,未显示“Choose file”按钮,仅显示string($uri)输入框,无法进行文件上传操作。相关代码如下:

core/models.py

def office_image_file_path(instance, filename):
    ext = filename.split('.')[-1]
    filename = f'{uuid.uuid4()}.{ext}'

    return os.path.join('uploads/office/', filename)

class Office(models.Model):
    # Other fields...
    image = models.ImageField(null=True, upload_to=office_image_file_path)

office/serializer.py

class OfficeSerializer(serializers.ModelSerializer):    
    class Meta:
        """Meta class for OfficeSerializer."""

        model = Office
        fields = "__all__"

class OfficeImageSerializer(serializers.ModelSerializer):
    """Serializer for uploading images to recipes"""

    class Meta:
        model = Office
        fields = ('id', 'image')
        read_only_fields = ('id',)
        extra_kwargs = {'image': {'required': True}}

office/views.py

class OfficeViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows offices to be viewed or edited if authenticated.
    """
    queryset = Office.objects.all()
    serializer_class = OfficeSerializer
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        """
        Retrive offices for authenticated users.
        """
        return self.queryset.filter(user=self.request.user)

    def get_serializer_class(self):
        if self.action == 'upload_image':
            return OfficeImageSerializer

        return OfficeSerializer

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

    @action(methods=['POST'], detail=True, url_path='upload-image')
    def upload_image(self, request, pk=None):
        office = self.get_object()
        print(request.data)  # Debug: Print the request data
        serializer = self.get_serializer(
            office,
            data=request.data
        )

        if serializer.is_valid():
            serializer.save()
            return Response(
                serializer.data,
                status=status.HTTP_200_OK
            )

        return Response(
            serializer.errors,
            status=status.HTTP_400_BAD_REQUEST
        )

解决方法

方法1:为ImageField指定Swagger文件类型注解

修改OfficeImageSerializer,明确告诉Swagger该字段为文件上传类型:

from drf_yasg import openapi

class OfficeImageSerializer(serializers.ModelSerializer):
    """Serializer for uploading images to recipes"""
    image = serializers.ImageField(
        required=True,
        swagger_schema_fields={
            'type': 'file',
            'description': 'Office image file'
        }
    )

    class Meta:
        model = Office
        fields = ('id', 'image')
        read_only_fields = ('id',)

方法2:在视图动作上配置请求体格式

在upload_image动作中,手动指定请求体为multipart/form-data类型:

from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi

class OfficeViewSet(viewsets.ModelViewSet):
    # ... 其他代码 ...

    @swagger_auto_schema(
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'image': openapi.Schema(type=openapi.TYPE_FILE, description='Image file')
            },
            required=['image']
        ),
        consumes=['multipart/form-data']
    )
    @action(methods=['POST'], detail=True, url_path='upload-image')
    def upload_image(self, request, pk=None):
        # ... 原有代码 ...

方法3:检查DRF-YASG基础配置

确保项目已安装drf-yasg,并在urls.py中正确配置Swagger视图:

from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from rest_framework import permissions

schema_view = get_schema_view(
    openapi.Info(
        title="Office API",
        default_version='v1',
        description="API for office management",
    ),
    public=True,
    permission_classes=[permissions.AllowAny],
)

urlpatterns = [
    # ... 其他路由 ...
    path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
]

原理说明

Swagger默认会将ImageField解析为字符串类型(URI),因为DRF序列化ImageField时返回的是图片URL。但上传场景需要明确指定字段为文件类型,并要求使用multipart/form-data格式接收请求,通过上述配置即可让Swagger显示文件选择按钮。

内容的提问来源于stack exchange,提问作者joaovitorpigozzo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 21:24:52