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

Fields which have a resolve method in ModelSchema are no longer parsed in put requests.

Open 21adrian1996 opened this issue 1 year ago • 3 comments

Describe the bug Fields which have a resolve method in ModelSchema are no longer parsed in put requests.

Versions:

  • Python version: 3.10
  • Django version: 4.2.7
  • Django-Ninja version: 1.0.1
  • Pydantic version: 2.5.1

In Ninja v0 I had

class MyModelSchema(ModelSchema):
    my_field_from_model_2: str

    class Config:
        model = models.MyModel
        model_fields = ['id', 'my_field_from_model_1']

    @staticmethod
    def resolve_my_field_from_model_2(obj):
        # code to resolve field would be here, just return it as it is for the example
        return obj.my_field_from_model_2

I switch class Config to Meta and model_fields to fields for ninja v1.

In v1 each field which has a custom resolve method (e.g my_field_from_model_2) is no longer included in the payload.dict() when doing a PUT request. In v0 this worked and the field was included.

Is this on purpose no longer available per default and is there any way to activate this again? I could not really find any model_config in pydantic which allows that.

Quickfix would be to use different schemas for GET and PUT, but it would be nice if it could be done with the same one.

21adrian1996 avatar Nov 22 '23 11:11 21adrian1996

@21adrian1996

hard to tell... could you show the code you have for v1 ?

vitalik avatar Nov 22 '23 12:11 vitalik

The code for version 1 is basically the same with the new naming:

class MyModelSchema(ModelSchema):
    model_config = ConfigDict(
        extra='allow'
    )
    my_field_from_model_2: str

    class Meta:
        model = models.MyModel
        fields = ['id', 'my_field_from_model_1']

    @staticmethod
    def resolve_my_field_from_model_2(obj):
        # code to resolve field would be here, just return it as it is for the example
        return obj.my_field_from_model_2

Note: model_config does not seem to change this.

Then the API is something like

@router.put('/mymodel')
def put_mymodel(request, payload: MyModelSchema):
    pl = payload.dict()

where all fields which have a resolve_ method are not included in pl.

21adrian1996 avatar Nov 22 '23 13:11 21adrian1996

@21adrian1996

so this is a bit backward incompatible thing - in pydantic2 all orm-mode objects converted from dict to objects

in new version - object that you got in resolver is matching the the input data (like in this case it's dict as it was an JSON input)

so you should change your code like this:

    @staticmethod
    def resolve_my_field_from_model_2(obj: dict):
        return obj["my_field_from_model_2"]  # <-- !!!

vitalik avatar Nov 22 '23 13:11 vitalik