I am trying to create a simple restful API using Django-ninja.
Here is the post method to add a new record:
@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"}
This endo point works without a problem. The next step is to create a put endpoint.
@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
Unfortunately, the put endpoint does not work as intended. There is no error raised but the file fields are neither sending the files nor getting a value (The value is None).
I used the swagger and uploaded the file using it.
But file upload does not work.
Update
If I change the HTTP Method to POST it works. But it does not work with PUT method.
Found where the problem lies. It was not on my side but on the
django-ninja's side. The framework does not support file upload withPUTandPATCHmethods.However, there is a solution:
https://github.com/vitalik/django-ninja/pull/719, https://pypi.org/project/ninja-put-patch-file-upload-middleware/
Solution:
First, install the middleware:
Add it on settings file:
Now the
PUTandPATCHmethods will accept file uploads.Unittest
Please be aware that this solution lacks the ability to unit test the code using
Django's builtinTestCaseclass.