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

Django Ninja中PUT接口无法更新FileField的问题求助

Django-Ninja PUT接口无法上传文件问题

我用Django-ninja搭建RESTful API,新增记录的post接口运行正常:

@router.post('/add',
             response={201: WordSchema, 401: DefaultSchema, 404: DefaultSchema},
             tags=["Dictionary"])
def add_word(request, lang1: str, lang2: str, word_class: int = None,
             description: str = None, example: str = None,
             sound: UploadedFile = None, image: UploadedFile = None):
    if not request.auth.is_superuser:
        return 401, {"detail": "Unauthorized"}
    try:
        if word_class is not None:
            word_class = WordClass.objects.get(pk=word_class)
        word = Word.objects.create(
            created_by=request.auth, lang1=lang1, lang2=lang2,
            word_class=word_class,
            description=description,
            example=example,
            sound=sound,
            image=image
        )
        return 201, word
    except WordClass.DoesNotExist:
        return 404, {"detail": "WordClass Does not exist"}

但后续写的put接口无法正常处理文件上传:调用无报错,但sound和image字段始终为None,用Swagger测试也没用。将HTTP方法改成POST就能正常工作,PUT不行。PUT接口代码如下:

@router.put('/put',
            response={200: DefaultSchema, 201: WordSchema,
                      401: DefaultSchema, 404: DefaultSchema,
                      409: DefaultSchema},
            tags=["Dictionary"])
def put_word(request, item_id: int, lang1: str, lang2: str,
             description: str = None, example: str = None,
             word_class: int = None, sound: UploadedFile = None,
             image: UploadedFile = None):
    if not request.auth.is_superuser:
        return 401, {"detail": "Unauthorized"}
    try:
        if word_class is not None:
            word_class = WordClass.objects.get(pk=word_class)
        word = Word.objects.get(pk=item_id)
        word.lang1 = lang1
        word.lang2 = lang2
        word.word_class = word_class
        word.description = description
        word.example = example
        word.sound = sound
        word.image = image
        word.save()
        return 200, {"detail": "Record updated"}
    except WordClass.DoesNotExist:
        return 404, {"detail": "WordClass Does not exist"}
    except Word.DoesNotExist:
        word = Word.objects.create(created_by=request.auth,
                                   lang1=lang1, lang2=lang2,
                                   word_class=word_class,
                                   sound=sound, image=image)
        return 201, word

问题原因及解决方案

Django-Ninja默认不会为PUT方法自动解析multipart/form-data请求,而文件上传必须依赖这个格式,POST方法默认支持该格式,所以能正常工作。

解决方法:

  • 给PUT接口添加openapi_extra配置,强制指定请求内容类型为multipart/form-data,同时让Swagger正确识别上传字段:
@router.put('/put',
            response={200: DefaultSchema, 201: WordSchema,
                      401: DefaultSchema, 404: DefaultSchema,
                      409: DefaultSchema},
            tags=["Dictionary"],
            openapi_extra={
                "requestBody": {
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "item_id": {"type": "integer"},
                                    "lang1": {"type": "string"},
                                    "lang2": {"type": "string"},
                                    "description": {"type": "string"},
                                    "example": {"type": "string"},
                                    "word_class": {"type": "integer"},
                                    "sound": {"type": "string", "format": "binary"},
                                    "image": {"type": "string", "format": "binary"},
                                },
                                "required": ["item_id", "lang1", "lang2"]
                            }
                        }
                    }
                }
            })
  • 优化文件字段更新逻辑:当前代码如果用户没传新文件,会把原有文件值覆盖为None,建议调整为仅在有新文件时更新:
# 替换原有的直接赋值
if sound is not None:
    word.sound = sound
if image is not None:
    word.image = image

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 07:12:05