Skip to content

Commit 5a4cbe7

Browse files
authored
add register_type public function (#1352)
* register_field utility * mypy lint
1 parent 97ef291 commit 5a4cbe7

File tree

4 files changed

+37
-4
lines changed

4 files changed

+37
-4
lines changed

ninja/conf.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class Settings(BaseModel):
1111
"ninja.pagination.LimitOffsetPagination", alias="NINJA_PAGINATION_CLASS"
1212
)
1313
PAGINATION_PER_PAGE: int = Field(100, alias="NINJA_PAGINATION_PER_PAGE")
14-
PAGINATION_MAX_LIMIT: int = Field(inf, alias="NINJA_PAGINATION_MAX_LIMIT")
14+
PAGINATION_MAX_LIMIT: int = Field(inf, alias="NINJA_PAGINATION_MAX_LIMIT") # type: ignore
1515

1616
# Throttling
1717
NUM_PROXIES: Optional[int] = Field(None, alias="NINJA_NUM_PROXIES")

ninja/orm/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from ninja.orm.factory import create_schema
2+
from ninja.orm.fields import register_field
23
from ninja.orm.metaclass import ModelSchema
34

4-
__all__ = ["create_schema", "ModelSchema"]
5+
__all__ = ["create_schema", "register_field", "ModelSchema"]

ninja/orm/fields.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from pydantic.fields import FieldInfo
1010
from pydantic_core import PydanticUndefined, core_schema
1111

12+
from ninja.errors import ConfigError
1213
from ninja.openapi.schema import OpenAPISchema
1314
from ninja.types import DictStrAny
1415

@@ -81,6 +82,10 @@ def validate(cls, value: Any, _: Any) -> Any:
8182
TModel = TypeVar("TModel")
8283

8384

85+
def register_field(django_field: str, python_type: Any) -> None:
86+
TYPES[django_field] = python_type
87+
88+
8489
@no_type_check
8590
def create_m2m_link_type(type_: Type[TModel]) -> Type[TModel]:
8691
class M2MLink(type_): # type: ignore
@@ -148,7 +153,15 @@ def get_schema_field(
148153
max_length = field_options.get("max_length")
149154

150155
internal_type = field.get_internal_type()
151-
python_type = TYPES[internal_type]
156+
try:
157+
python_type = TYPES[internal_type]
158+
except KeyError as e:
159+
msg = [
160+
f"Do not know how to convert django field '{internal_type}'.",
161+
"Try from ninja.orm import register_field",
162+
f"register_field('{internal_type}', <your-python-type>)",
163+
]
164+
raise ConfigError("\n".join(msg)) from e
152165

153166
if field.primary_key or blank or null or optional:
154167
default = None

tests/test_orm_schemas.py

+20-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from util import pydantic_ref_fix
99

1010
from ninja.errors import ConfigError
11-
from ninja.orm import create_schema
11+
from ninja.orm import create_schema, register_field
1212
from ninja.orm.shortcuts import L, S
1313

1414

@@ -581,3 +581,22 @@ class Meta:
581581
SomeReqFieldModel, optional_fields=["some_field", "other_field", "optional"]
582582
)
583583
assert Schema.json_schema().get("required") is None
584+
585+
586+
def test_register_custom_field():
587+
class MyCustomField(models.Field):
588+
description = "MyCustomField"
589+
590+
class ModelWithCustomField(models.Model):
591+
some_field = MyCustomField()
592+
593+
class Meta:
594+
app_label = "tests"
595+
596+
with pytest.raises(ConfigError):
597+
create_schema(ModelWithCustomField)
598+
599+
register_field("MyCustomField", int)
600+
Schema = create_schema(ModelWithCustomField)
601+
print(Schema.json_schema())
602+
assert Schema.json_schema()["properties"]["some_field"]["type"] == "integer"

0 commit comments

Comments
 (0)