I can't upload an image to my database at all

I'm using django ninja back end the code works but when I try to send it through an application that I'm making using javascript or even with bash it doesn't work

i've tryed

`def upload_media(request, nome:str, imgurl: UploadedFile ):

usuarios = Media.objects.all()
Media.objects.create(nome = nome,imgurl=imgurl)

return 1`

and

class mediaSchema(Schema): nome : str imgurl: UploadedFile

`@api.post('tst/', response=mediaSchema) def upload_media2(request, infos : mediaSchema):

media = infos.dict() infos = Media(**media)

infos.save()

return 1`

Issues with code:

  • The UploadedFile type in imgurl isn't handled correctly.UploadedFile must be managed through Django's request.FILES, not directly as a parameter. The function retrieves usuarios = Media.objects.all() but doesn’t use it. This line is redundant. Also there’s no error handling for file uploads or invalid data. lasn but not least, the return value 1 is not meaningful.

    from django.http import JsonResponse
    from django.core.files.uploadedfile import UploadedFile
    
    def upload_media(request, nome: str, imgurl: UploadedFile):
        if request.method != "POST":
            return JsonResponse({"error": "Only POST method allowed"}, status=405)
    
      # Ensure file is uploaded via request.FILES
      if not request.FILES.get("imgurl"):
          return JsonResponse({"error": "File not uploaded"}, status=400)
    
      # Save the uploaded file
      imgurl = request.FILES["imgurl"]  # Retrieve the file from request
      media = Media.objects.create(nome=nome, imgurl=imgurl)
    
      return JsonResponse({"message": "Media uploaded successfully", "media_id": media.id})
    
  • class mediaSchema and upload_media2 issues: UploadedFile in mediaSchema doesn't work as expected with Django Ninja. Ninja uses File(...) to handle file uploads. infos.dict() won't handle UploadedFile properly because it isn’t a serializable field. Attempting to directly create a Media object from mediaSchema (Media(**media)) is incorrect because imgurl is not a compatible field

    from ninja import Schema, File
    from django.core.files.uploadedfile import UploadedFile
    from ninja import ModelSchema
    
    class MediaSchema(Schema):
        nome: str
        imgurl: UploadedFile
    
    @api.post('tst/', response={200: str, 400: str})
    def upload_media2(request, nome: str, imgurl: UploadedFile = File(...)):
        try:
          media = Media.objects.create(nome=nome, imgurl=imgurl)
          return 200, "Media uploaded successfully!"
      except Exception as e:
          return 400, f"Error occurred: {str(e)}"
    

The problem is that you didn't declare the schema correctly in the first case, file, should be specified separately, you did it correctly, and all the other (additional) fields should have been specified as Form schema, not as nome:str. So, in the first case, your controller should look something like this:

from ninja import Form, Schema, UploadedFile

app = NinjaAPI()


class UserDetailsSchema(Schema):
    username: str


@app.post("/upload/")
def upload_media(request, details: Form[UserDetailsSchema], input_file: UploadedFile):
    return {'username': details.username, 'file_name': input_file.name}

The result will be roughly the following code to send using javascript:

formData.append('username', 'Alex');
formData.append('input_file', file);
await fetch('http://127.0.0.1:8000/usuarios/api/upload/', {
    body:formData,
    method: 'POST',
    // something extra
}).then(response=> response.json()).then(result => console.log(result))
// console.log output => {username: 'Alex', file_name: 'test.png'}

Or it could be done using another option:

from ninja import File, Schema, UploadedFile

app = NinjaAPI()


class UserDetailsSchema(Schema):
    username: str


@app.post("/upload/")
def upload_media(
        request, 
        details: UserDetailsSchema, 
        #  or => input_file: UploadedFile
        input_file: File[UploadedFile]):
    return {'details': details, 'file_name': input_file.name}

Accordingly, the code to send the data to javascript should look something like this:

formData.append('details', JSON.stringify({ username: 'Alex' }));
formData.append('input_file', file);
await fetch('http://127.0.0.1:8000/usuarios/api/upload/', {
    body:formData,
    method: 'POST',
}).then(response=> response.json()).then(result => console.log(result))
// console.log output => {details: {username: 'Alex'}, file_name: 'test.png'}

That should work, in general the documentation seems to give clear examples I think.

Back to Top