vitalik / django-ninja

💨 Fast, Async-ready, Openapi, type hints based framework for building APIs
https://django-ninja.dev
MIT License
7.06k stars 422 forks source link

422 and Validation Errors #491

Closed cltrudeau closed 2 years ago

cltrudeau commented 2 years ago

I'm not sure if I'm just reading the docs incorrectly, or if I have something set up wrong, but I was accidentally sending a malformed date which was causing a ValidationError.

The docs say

Any other unhandled exception by application.

Default behavior

if settings.DEBUG is True - returns a traceback in plain text (useful when debugging in console or swagger UI)
else - default django exception handler mechanism is used (error logging, email to ADMINS)

But it is unclear if that is for other exceptions or for those caught like Validation errors.

I have debug on, and am running the dev server. All I get is the "Unprocessable Entity" error with a 422. No details about what was happening. Took me quite some time to even figure out where this was being raised (I was grepping "Unprocessable Entity" which didn't get me anywhere).

So, question: do I need to do something to get the detailed error info in the dev server's stdout?

and if not, this becomes a feature request to get that info on the screen somehow.

Love the library. Keep up the good work.

vitalik commented 2 years ago

Hi @cltrudeau

the DEBUG statement is about uncaught exceptions (i.e. 500 errors)

the validation errors are the expected behavoiur of the application (users can input invalid dates, numbers etc) - so it returns 422 http code

I have debug on, and am running the dev server. All I get is the "Unprocessable Entity" error with a 422. No details about what was happening. Took me quite some time to even figure out where this was being raised (I was grepping "Unprocessable Entity" which didn't get me anywhere).

Validation Error should give you all the information about the fields that was not validated in json response ...

Maybe bring some code sample ? you did not override default exceptions ?

cltrudeau commented 2 years ago

Hi @vitalik,

Thanks for the quick reply. I don't think I'm doing anything fancy. I didn't even realize you could write custom exception handlers until I started trying to squish my bug.

Code snippet:

class JobIn(ModelSchema):
    class Config:
        model = Job
        model_fields = ['name', 'state', 'expected_delivery', 'invoice_no']

@router.post('/jobs/{client_id}/{queue_id}/{spec_id}', url_name="create_job")
def create_job(request, client_id:int, queue_id:int, spec_id:int,
        payload: JobIn):

Where "expected_delivery" is a date. I was sending in "" instead of null for the blank. This produces the following in the console:

Unprocessable Entity: /api/control/jobs/4/3/5
[29/Jun/2022 21:51:59] "POST /api/control/jobs/4/3/5 HTTP/1.1" 422 121

No mention of this being a validation problem, no mention of the fact that the date field was causing the problem.

I'm running Django 4.0. Default setup, no loggers. Debug is True.

Once I figured out where the error was being thrown inside the library, I instrumented it and had it print out the errors dictionary and that was what made me understand what was going on.

I'd think the default behaviour should be to have some of that info showing up in the console, at least when Debug is True.

If that is the expected behaviour, any idea why it might not be happening in my case?

vitalik commented 2 years ago

@cltrudeau

Well the idea is that when you use swagger UI (or chrome dev tools) you should see the responses with details:

CleanShot 2022-07-01 at 16 01 04@2x

by default validation errors are not flushed to console

but you can modify this behaviour with custom error handler:

from ninja.errors import ValidationError

api = NinjaAPI()

@api.exception_handler(ValidationError)
def custom_validation_errors(request, exc):
    print(exc.errors)  # <--------------------- !!!!
    return api.create_response(request, {"detail": exc.errors}, status=422)

then it will start printing details to console as well

cltrudeau commented 2 years ago

Ok. Got it.

I'd suggest there is value in having it show in the console, but I at least now understand what's going on. Thanks for being responsive to my questions.