0

I'm trying to add an UploadedFile parameter to the PUT method in my Ninja router. The same parameter works perfectly fine with the POST method, but when I try to use it with the PUT method, Ninja returns the error:

Code
422

Details Error: Unprocessable Entity

Response body

{
  "detail": [
    {
      "loc": [
        "body",
        "profile_in"
      ],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

which doesn't make sense to me, because I'm passing all the required parameters in the profile_in. here's the curl command that the swagger is providing:

curl -X 'PUT' \
  'http://127.0.0.1:8000/api/profile/edit_profile' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer <My Token>' \
  -H 'Content-Type: multipart/form-data' \
  -F 'img=@IMG_20220425_094322_906.JPG;type=image/jpeg' \
  -F 'profile_in={
  "name": "Hassan",
  "title": "Web",
  "bio": "string",
  "skills": [
    {
      "name": "Django"
    },
    {
      "name": "HTML/CSS"
    }
  ]
}'

here is my post method:

@profile_controller.post("create_profile",
                         response={200: ProfileSchemaOut, 
                                   404: MessageOut,
                                   400: MessageOut,
                                   },
                        auth=CustomAuth(),
                        )
def create_profile(request, profile_in:ProfileSchemaIn, img:UploadedFile=None):

and the put method:

@profile_controller.put("edit_profile",
                         response={200: ProfileSchemaOut, 
                                   404: MessageOut,
                                   400: MessageOut,
                                   },
                        auth=CustomAuth(),
                        )
def edit_profile(request, profile_in: ProfileSchemaIn, img:Optional[UploadedFile]=File(None)):

I don't know if this is relevant but this is my ProfileSchemaIn

class ProfileSchemaIn(ProfileSchema):
    name: str
    title: str
    bio: Optional[str] = None
    skills: Optional[List[SkillSchema]]

I know I can use bas64 for storing the img but I want to use the UploadedFile

1 Answers1

0

Upon examining the provided curl command and your code, I noticed that the curl command is missing the 'img' parameter. Additionally, the 'profile_in' parameter should be passed as separate form fields instead of being embedded in a JSON string.

Here's an updated curl command that includes the 'img' parameter and passes the 'profile_in' parameters as separate form fields:

curl -X 'PUT' \
  'http://127.0.0.1:8000/api/profile/edit_profile' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer <my token>' \
  -H 'Content-Type: multipart/form-data' \
  -F 'name=Hassan' \
  -F 'title=Web Developer' \
  -F 'bio=string' \
  -F 'skills=[{"name":"Django"}]' \
  -F 'img=@/path/to/your/image.jpg'

For your Ninja router methods, the input parameters should be defined as follows:

from pydantic import BaseModel
from typing import List

class ProfileInput(BaseModel):
    name: str
    title: str
    bio: Optional[str] = None
    skills: Optional[List[SkillSchema]]

@profile_controller.post("create_profile",
                         response={200: ProfileSchemaOut, 
                                   404: MessageOut,
                                   400: MessageOut,
                                   },
                        auth=CustomAuth(),
                        )
def create_profile(request, profile_in: ProfileInput = Body(...), img: UploadedFile = File(None)):

@profile_controller.put("edit_profile",
                         response={200: ProfileSchemaOut, 
                                   404: MessageOut,
                                   400: MessageOut,
                                   },
                        auth=CustomAuth(),
                        )
def edit_profile(request, profile_in: ProfileInput = Body(...), img: Optional[UploadedFile] = File(None)):