vitalik / django-ninja

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

ModelSchema inheritance #1300

Open Ksauder opened 1 month ago

Ksauder commented 1 month ago

I would like to be able to inherit from ModelSchemas so I can add a configuration layer where I can add custom functionality to the underlying pydantic BaseModel and then inherit this ProjectModelSchema to create my model schemas. I believe the reason this functionality is broken is due to the underlying logic surrounding the use of create_schema in ModelSchemaMetaclass which stops any inheritance chain using ModelSchema. Multiple inheritance works in some cases, but I'd like to stay away from that.

Desire:

class ProjectModelSchema(ModelSchema):
    _custom_serializer = pydantic.model_serializer(mode="wrap")(_project_custom_serializer)

class ItemModelSchema(ProjectModelSchema):
    # custom serializer is inherited
    customfield: Optional[str] = None

    class Meta:
        model = Item
        fields = ["id", "name"]

class ChildItemModelSchema(ItemModelSchema):
    # custom serializer and custom field are inherited
    class Meta(ItemModelSchema.Meta):
        model = SubItem
        fields = ItemModelSchema.Meta.fields + ["childfield"]

Problems:

  1. You actually can't inherit from ModelSchema more than one deep. Example:
    
    class ItemModelSchema(ModelSchema):
    class Meta:
        model = Item
        fields = ["id", "slug"]

class ChildItemModelSchema(ItemModelSchema):

this Meta is completely ignored

class Meta:
    model = Item
    fields = ["id", "slug", "name"]


2. You cannot currently create a ModelSchema class without specifying an internal Meta class which completely blocks the desired inheritance without multiple inheritance.

If I missed something please point it out.