Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct usage of ForeignKey Ids in Model Schema #1303

Open
kevingill1966 opened this issue Sep 24, 2024 · 1 comment
Open

Correct usage of ForeignKey Ids in Model Schema #1303

kevingill1966 opened this issue Sep 24, 2024 · 1 comment

Comments

@kevingill1966
Copy link

kevingill1966 commented Sep 24, 2024

I want to write a CRUD style API. I retrieve the model data, and save the model data. I want to do that using the schema mapped from the Django Model.

When I try it, the schema serialises using the django model attribute name. However, the validator expects the _id suffix. I am looking for the recommended way to configure the ModelSchema below to generate a JSON version with the attribute "content_type_id", instead of "content_type".

Here is an example. Execute using "python manage.py shell"

from django.contrib.auth.models import Permission
from pprint import pp
from ninja import ModelSchema, Field


class PermissionSchema(ModelSchema):
    class Meta:
        model = Permission
        fields = "__all__"


perm = Permission.objects.first()
serialiser = PermissionSchema.from_orm(perm)
d = serialiser.dict()
pp(d)

# {'id': 5, 'name': 'Can add group', 'content_type': 2, 'codename': 'add_group'}

PermissionSchema.model_validate(d)

# Traceback (most recent call last):
#   File "<console>", line 1, in <module>
#   File "/home/vscode/.local/lib/python3.11/site-packages/pydantic/main.py", line 596, in model_validate
#     return cls.__pydantic_validator__.validate_python(
#            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# pydantic_core._pydantic_core.ValidationError: 1 validation error for PermissionSchema
# content_type_id
#   Field required [type=missing, input_value=<DjangoGetter: {'id': 5, ...codename': 'add_group'}>, input_type=DjangoGetter]
#     For further information visit https://errors.pydantic.dev/2.9/v/missing

If I move the field content_type to content_type_id, it can parse

d["content_type_id"] = d.pop("content_type")

PermissionSchema.model_validate(d)
# PermissionSchema(id=5, name='Can add group', content_type=2, codename='add_group')

Note - the property name in the schema is "content_type_id", but the generated output is "content_type"

pp(PermissionSchema.schema())

# {'properties': {'id': {'anyOf': [{'type': 'integer'}, {'type': 'null'}],
#                        'title': 'ID'},
#                 'name': {'maxLength': 255, 'title': 'Name', 'type': 'string'},
#                 'content_type_id': {'title': 'Content Type', 'type': 'integer'},
#                 'codename': {'maxLength': 100,
#                              'title': 'Codename',
#                              'type': 'string'}},
#  'required': ['name', 'content_type_id', 'codename'],
#  'title': 'PermissionSchema',
#  'type': 'object'}
@kevingill1966
Copy link
Author

I found a discussion on this issue: #444

The authors:

  1. defined a custom property for the _id attribute
  2. excluded the foreign key from the field in the Meta section
from django.contrib.auth.models import Permission
from pprint import pp
from ninja import ModelSchema, Field


class PermissionSchema(ModelSchema):
    content_type_id: int
    class Meta:
        model = Permission
        fields = ['id', 'name', 'codename']


perm = Permission.objects.first()
serialiser = PermissionSchema.from_orm(perm)
d = serialiser.dict()
pp(d)

# {'content_type_id': 2,  'id': 5,  'name': 'Can add group',  'codename': 'add_group'}

This dictionary validates correctly

x = PermissionSchema.model_validate(d)
x.dict()
# {'content_type_id': 2, 'id': 5, 'name': 'Can add group', 'codename': 'add_group'}

Is this the standard approach or is there a more automated mechanism?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant