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
相关产品推荐
相关产品推荐

