Skip to content

[BUG] ModelSchema excludes declared fields when using exclude but not when using fields #1630

@almazkun

Description

@almazkun

Dear Vitaliy and contributors! Thank you very much for a wonderful project!

Describe the bug
When creating a ModelSchema with declared fields, the behavior differs depending on whether fields or exclude is specified in the Meta class:

  • With fields: Declared fields are correctly preserved and model fields are filtered
  • With exclude: Declared fields are incorrectly removed from the schema

Versions (please complete the following information):

  • Python version: 3.14.0
  • Django version: 6.0
  • Django-Ninja version: 1.5.1
  • Pydantic version: 2.12.5

Note you can quickly get this by runninng in ./manage.py shell this line:

from django.db import models

from ninja.orm import ModelSchema
from pydantic import Field


class StatusChoice(models.IntegerChoices):
    NEGATIVE = 0, "Negative"
    POSITIVE = 1, "Positive"
    NOT_ASSESSED = 98, "Not assessed"
    UNK = 99, "Unknown"


class Response(models.Model):
    status = models.IntegerField(
        choices=StatusChoice, default=StatusChoice.NOT_ASSESSED
    )

class ResponseSchemaField(ModelSchema):
    status: str = Field(alias="get_status_display")
    class Meta:
        model = Response
        fields = ["id"]

class ResponseSchemaExclude(ModelSchema):
    status: str = Field(alias="get_status_display")
    class Meta:
        model = Response
        exclude = ["id"]

instance = Response.objects.create()
ResponseSchemaField.from_orm(instance)  # ✓ ResponseSchemaField(status='Not assessed', id=4)
ResponseSchemaExclude.from_orm(instance)  # ✗ ResponseSchemaExclude(status=98)

Expected Behavior
Both fields and exclude should respect explicitly declared fields in the schema class and only filter auto-generated model fields.

Actual Behavior
Using exclude removes declared fields from the generated schema, causing them to be replaced by model fields of the same name.

However, _selected_model_fields returns all fields when using exclude, causing declared fields to be overwritten.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions