django-ninja icon indicating copy to clipboard operation
django-ninja copied to clipboard

How can I determine if an optional field with a default value was included in the request or not?

Open tykling opened this issue 3 years ago • 1 comments

Hello :)

Thank you for django-ninja - it is fantastic.

I have a question about using a Schema which has one or more optional fields like so:

class TestSchema(Schema):
    foo: int = None
    bar: int = None
    baz: str = None

When I do a PUT request to update for example the foo field (only), then the body object I get in the api method also contains the bar and baz fields, with the default value None.

How can I determine if the bar and baz fields were supplied in the API call or added by ninja?

Thanks! :)

tykling avatar Sep 13 '22 09:09 tykling

Hi @tykling

Under the hood django-ninja uses pydantic - so you can use the .dict() method (link) with exclude_unset argument:

@api.get('/foo')
def foo(request, test: TestShema):
     data = test.dict(exclude_unset=True)  # !!!!
    # ^ data should have only the passed values

vitalik avatar Sep 15 '22 18:09 vitalik

Thank you, that works perfectly! :)

I think this means there could be a bug in the documentation CRUD demo app https://django-ninja.rest-framework.com/tutorial/other/crud/ in the update_employee view:

If the API is called without department_id in the request it will set department to None in the database, overwriting any value that was already there. Same thing for the birthdate field of course.

I think you can fix it by adding exclude_unset=True to the .dict() call.

tykling avatar Sep 26 '22 19:09 tykling

Thinking more about this I guess the example is correct, since it is a PUT (replace object) rather than a PATCH (update object). The example could include both for completeness, but is not wrong as it is now. Closing issue, thanks :)

tykling avatar Oct 01 '22 12:10 tykling