surenkov / django-pydantic-field

Django JSONField with Pydantic models as a Schema
https://pypi.org/project/django-pydantic-field/
Other
116 stars 12 forks source link

Django form with SchemaField raises AttributeError if JSON is invalid #28

Closed amyasnikov closed 1 year ago

amyasnikov commented 1 year ago

The error happens when you pass an invalid JSON inside the SchemaField

Python: 3.10.12 Django: 4.1.10 Pydantic: 1.10.2 django-pydantic-field: 0.2.8

Steps to reproduce:

from pydantic import BaseModel
from django.forms import Form
from django_pydantic_field.forms import SchemaField

class MySchema(BaseModel):
    a: int

class MyForm(Form):
    my_field = SchemaField(schema=MySchema)

f = MyForm(data={'my_field': "invalid json}}}"})
f.is_valid()  # <- here you'll get AttributeError

Traceback:

Traceback (most recent call last):
  File "pydantic/main.py", line 539, in pydantic.main.BaseModel.parse_raw
  File "pydantic/parse.py", line 37, in pydantic.parse.load_str_bytes
  File "/usr/local/lib/python3.10/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/local/lib/python3.10/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/local/lib/python3.10/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/django_pydantic_field/forms.py", line 40, in to_python
    return super().to_python(value)
  File "/usr/local/lib/python3.10/site-packages/django/forms/fields.py", line 1359, in to_python
    converted = json.loads(value, cls=self.decoder)
  File "/usr/local/lib/python3.10/json/__init__.py", line 359, in loads
    return cls(**kw).decode(s)
  File "/usr/local/lib/python3.10/site-packages/django_pydantic_field/base.py", line 75, in decode
    value = self.schema.parse_raw(obj).__root__  # type: ignore
  File "pydantic/main.py", line 548, in pydantic.main.BaseModel.parse_raw
pydantic.error_wrappers.ValidationError: 1 validation error for FieldSchema[MySchema]
__root__
  Expecting value: line 1 column 1 (char 0) (type=value_error.jsondecode; msg=Expecting value; doc=invalid json}}}; pos=0; lineno=1; colno=1)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python3.10/site-packages/django/forms/forms.py", line 205, in is_valid
    return self.is_bound and not self.errors
  File "/usr/local/lib/python3.10/site-packages/django/forms/forms.py", line 200, in errors
    self.full_clean()
  File "/usr/local/lib/python3.10/site-packages/django/forms/forms.py", line 437, in full_clean
    self._clean_fields()
  File "/usr/local/lib/python3.10/site-packages/django/forms/forms.py", line 449, in _clean_fields
    value = field.clean(value)
  File "/usr/local/lib/python3.10/site-packages/django/forms/fields.py", line 198, in clean
    value = self.to_python(value)
  File "/usr/local/lib/python3.10/site-packages/django_pydantic_field/forms.py", line 42, in to_python
    raise ValidationError(e.errors(), code="invalid")
  File "/usr/local/lib/python3.10/site-packages/django/core/exceptions.py", line 167, in __init__
    message = ValidationError(message)
  File "/usr/local/lib/python3.10/site-packages/django/core/exceptions.py", line 160, in __init__
    self.error_dict[field] = messages.error_list
AttributeError: 'ValidationError' object has no attribute 'error_list'
surenkov commented 1 year ago

Hi @amyasnikov, thanks for pointing on that issue!

I've fixed that in #29, will push it with a new release today.