Skip to content

Commit

Permalink
fix inheriting class overwriting parents django fields
Browse files Browse the repository at this point in the history
  • Loading branch information
Ksauder committed Sep 25, 2024
1 parent 424d314 commit 07f48a8
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 1 deletion.
7 changes: 6 additions & 1 deletion ninja/orm/metaclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,17 @@ def __new__(
meta_conf = MetaConf.model_validate(conf_dict)

if meta_conf and meta_conf.model:
base_model_fields = {}
for base in bases:
base_model_fields.update(**base.model_fields)

meta_conf = meta_conf.model_dump(exclude_none=True)

fields = factory.convert_django_fields(**meta_conf)
namespace.setdefault("__annotations__", {})
for field, val in fields.items():
if not namespace["__annotations__"].get(field, None):
# don't overwrite custom fields in annotations or previous django fields in base_model_fields
if not namespace["__annotations__"].get(field, None) and not base_model_fields.get(field, None):
# set type
namespace["__annotations__"][field] = val[0]
# and default value
Expand Down
72 changes: 72 additions & 0 deletions tests/test_orm_metaclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,3 +531,75 @@ class Meta(ItemBaseModelSchema.Meta):
"title": "ItemInMealsSchema",
"type": "object",
}


def test_inherited_tables():
class Foreign(models.Model):
name = models.CharField()

class Meta:
app_label = "tests"


class Item(models.Model):
id = models.PositiveIntegerField(primary_key=True)
slug = models.CharField(blank=True, null=True)
ref = models.ForeignKey(Foreign, on_delete=models.PROTECT)

class Meta:
app_label = "tests"
abstract = True


class DiffItem(Item):
special = models.CharField()

class Meta:
app_label = "tests"


class ForeignModelSchema(ModelSchema):
class Meta:
model = Foreign
fields = "__all__"


class ItemModelSchema(ModelSchema):
ref: ForeignModelSchema
class Meta:
model = Item
fields = "__all__"

class DiffItemModelSchema(ItemModelSchema):
special: str

class Meta(ItemModelSchema.Meta):
model = DiffItem

class OptionalDiffItemModelSchema(ItemModelSchema):
special: str
ref: Optional[ForeignModelSchema] = None

class Meta(ItemModelSchema.Meta):
model = DiffItem

# assert that DiffItemModelSchema did not overwrite ItemModelSchema.ref with a 0 depth 'ref_id:integer' field
j = DiffItemModelSchema.model_json_schema()
assert not j["properties"].get("ref_id", None)
assert j["properties"].get("ref", None)

# assert custom annotation can overwrite the ref field
j = OptionalDiffItemModelSchema.model_json_schema()
assert not j["properties"].get("ref_id", None)
assert j["properties"].get("ref", None) == {
'anyOf': [
{
'$ref': '#/$defs/ForeignModelSchema',
},
{
'type': 'null',
},
],
'default': None,
}
assert "ref" not in j["required"]

0 comments on commit 07f48a8

Please sign in to comment.