diff --git a/.github/workflows/test_full.yml b/.github/workflows/test_full.yml index 21fe5de66..c81f2f33a 100644 --- a/.github/workflows/test_full.yml +++ b/.github/workflows/test_full.yml @@ -22,7 +22,7 @@ jobs: - name: Install core run: pip install "Django${{ matrix.django-version }}" pydantic - name: Install tests - run: pip install pytest pytest-asyncio pytest-django + run: pip install pytest pytest-asyncio pytest-django psycopg2 - name: Test run: pytest diff --git a/ninja/orm/fields.py b/ninja/orm/fields.py index b7766c542..854c6488c 100644 --- a/ninja/orm/fields.py +++ b/ninja/orm/fields.py @@ -15,6 +15,15 @@ from django.db.models import ManyToManyField from django.db.models.fields import Field + +try: + from django.contrib.postgres.fields.array import ArrayField +except ModuleNotFoundError: # pragma no cover + # psycopg2 not installed. ok to make a dummy here since it can't be in use + class ArrayField: # type: ignore[no-redef] + pass + + from pydantic import IPvAnyAddress from pydantic.fields import FieldInfo, Undefined @@ -117,8 +126,13 @@ def get_schema_field(field: Field, *, depth: int = 0) -> Tuple: null = field_options.get("null", False) max_length = field_options.get("max_length") - internal_type = field.get_internal_type() - python_type = TYPES[internal_type] + if isinstance(field, ArrayField): + inner_internal_type = field.base_field.get_internal_type() + inner_python_type = TYPES[inner_internal_type] + python_type = List[inner_python_type] # type: ignore[valid-type] + else: + internal_type = field.get_internal_type() + python_type = TYPES[internal_type] if field.has_default(): if callable(field.default): diff --git a/pyproject.toml b/pyproject.toml index a31196b37..319fecbe5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,6 +62,7 @@ test = [ "flake8", "mypy==0.931", "django-stubs", + "psycopg2", ] doc = [ "mkdocs", diff --git a/tests/test_orm_schemas.py b/tests/test_orm_schemas.py index fe7f3e8a1..d3ecdeac1 100644 --- a/tests/test_orm_schemas.py +++ b/tests/test_orm_schemas.py @@ -3,6 +3,7 @@ import django import pytest +from django.contrib.postgres.fields.array import ArrayField from django.db import models from django.db.models import Manager @@ -45,6 +46,7 @@ def test_all_fields(): # test all except relational field class AllFields(models.Model): + arrayfield = ArrayField(models.IntegerField()) bigintegerfield = models.BigIntegerField() binaryfield = models.BinaryField() booleanfield = models.BooleanField() @@ -82,6 +84,11 @@ class Meta: "type": "object", "properties": { "id": {"title": "Id", "type": "integer"}, + "arrayfield": { + "title": "Arrayfield", + "type": "array", + "items": {"type": "integer"}, + }, "bigintegerfield": {"title": "Bigintegerfield", "type": "integer"}, "binaryfield": { "title": "Binaryfield", @@ -139,6 +146,7 @@ class Meta: "uuidfield": {"title": "Uuidfield", "type": "string", "format": "uuid"}, }, "required": [ + "arrayfield", "bigintegerfield", "binaryfield", "booleanfield",