def test_custom_fields(): class SmallModel(models.Model): f1 = models.CharField() f2 = models.CharField() class Meta: app_label = "tests" Schema1 = create_schema(SmallModel, custom_fields=[("custom", int, ...)]) assert Schema1.schema() == { "title": "SmallModel", "type": "object", "properties": { "id": { "title": "Id", "type": "integer" }, "f1": { "title": "F1", "type": "string" }, "f2": { "title": "F2", "type": "string" }, "custom": { "title": "Custom", "type": "integer" }, }, "required": ["f1", "f2", "custom"], } Schema2 = create_schema(SmallModel, custom_fields=[("f1", int, ...)]) print(Schema2.schema()) assert Schema2.schema() == { "title": "SmallModel", "type": "object", "properties": { "id": { "title": "Id", "type": "integer" }, "f1": { "title": "F1", "type": "integer" }, "f2": { "title": "F2", "type": "string" }, }, "required": ["f1", "f2"], }
def test_exceptions(): class MyModel2(models.Model): f1 = models.CharField() f2 = models.CharField() class Meta: app_label = "tests" with pytest.raises(ConfigError): create_schema(MyModel2, fields=["f1"], exclude=["f2"]) with pytest.raises(ConfigError): create_schema(MyModel2, fields=["f_invalid"])
def test_exceptions(): class MyModel2(models.Model): f1 = models.CharField() f2 = models.CharField() class Meta: app_label = "tests" with pytest.raises( ConfigError, match="Only one of 'fields' or 'exclude' should be set."): create_schema(MyModel2, fields=["f1"], exclude=["f2"]) with pytest.raises(ConfigError): create_schema(MyModel2, fields=["f_invalid"])
def test_not_duplicate_schema_names(): from ninja.openapi.schema import model_schema from ninja.schema import Schema class TestModelNotDuplicate(models.Model): charfield = models.CharField() class Meta: app_label = "tests" TestSchema = create_schema(TestModelNotDuplicate, name="TestModelNotDuplicate", fields=["charfield"]) with patch("ninja.openapi.schema.pydantic_model_schema", side_effect=ValueError): with pytest.raises(ValueError): assert model_schema() is None with patch("ninja.openapi.schema.pydantic_model_schema", side_effect=KeyError): with pytest.raises(KeyError): assert model_schema() is None with patch("ninja.openapi.schema.pydantic_model_schema", side_effect=KeyError(Schema)): with pytest.raises(KeyError): assert model_schema() is None with patch("ninja.openapi.schema.pydantic_model_schema", side_effect=KeyError(TestSchema)): with pytest.raises(KeyError): assert model_schema() is None # define a duplicate schema name create_schema( TestModelNotDuplicate, name="TestModelNotDuplicate", fields=["charfield"], custom_fields=[("test", TestSchema, ...) ], # interlinking models with the same name ) # duplicate orm schema names returns ConfigError with patch("ninja.openapi.schema.pydantic_model_schema", side_effect=KeyError(TestSchema)): with pytest.raises(ConfigError): assert model_schema() is None
def test_django_31_fields(): class ModelNewFields(models.Model): jsonfield = models.JSONField() positivebigintegerfield = models.PositiveBigIntegerField() class Meta: app_label = "tests" Schema = create_schema(ModelNewFields) print(Schema.schema()) assert Schema.schema() == { "title": "ModelNewFields", "type": "object", "properties": { "id": { "title": "Id", "type": "integer" }, "jsonfield": { "title": "Jsonfield", "type": "object" }, "positivebigintegerfield": { "title": "Positivebigintegerfield", "type": "integer", }, }, "required": ["jsonfield", "positivebigintegerfield"], }
def test_manytomany(): class SomeRelated(models.Model): f = models.CharField() class Meta: app_label = "tests" class ModelWithM2M(models.Model): m2m = models.ManyToManyField(SomeRelated, blank=True) class Meta: app_label = "tests" WithM2MSchema = create_schema(ModelWithM2M, exclude=["id"]) api = NinjaAPI() @api.post("/bar") def post_with_m2m(request, payload: WithM2MSchema): return payload.dict() client = TestClient(api) response = client.post("/bar", json={"m2m": [1, 2]}) assert response.status_code == 200, str(response.json()) assert response.json() == {"m2m": [1, 2]} response = client.post("/bar", json={"m2m": []}) assert response.status_code == 200, str(response.json()) assert response.json() == {"m2m": []}
def test_default(): class MyModel(models.Model): default_static = models.CharField(default="hello") default_dynamic = models.CharField(default=lambda: "world") class Meta: app_label = "tests" Schema = create_schema(MyModel) print(Schema.schema()) assert Schema.schema() == { "title": "MyModel", "type": "object", "properties": { "id": { "title": "Id", "type": "integer" }, "default_static": { "title": "Default Static", "default": "hello", "type": "string", }, "default_dynamic": { "title": "Default Dynamic", "type": "string" }, }, }
def test_manytomany(): class Foo(models.Model): f = models.CharField() class Meta: app_label = "tests" class Bar(models.Model): m2m = models.ManyToManyField(Foo, blank=True) class Meta: app_label = "tests" Schema = create_schema(Bar) # mocking database data: foo = Mock() foo.pk = 1 foo.f = "test" m2m = Mock(spec=Manager) m2m.all = lambda: [foo] bar = Mock() bar.id = 1 bar.m2m = m2m data = Schema.from_orm(bar).dict() assert data == {"id": 1, "m2m": [1]}
def get_related_field_schema(field: Field, *, depth: int): from ninja.orm import create_schema model = field.related_model schema = create_schema(model, depth=depth - 1) default = ... if not field.concrete and field.auto_created or field.null: default = None if isinstance(field, ManyToManyField): schema = List[schema] return ( schema, FieldInfo( default=default, description=field.help_text, title=field.verbose_name.title(), ), )
def test_bigautofield(): class ModelBigAuto(models.Model): bigautofiled = models.BigAutoField(primary_key=True) class Meta: app_label = "tests" SchemaCls = create_schema(ModelBigAuto) print(SchemaCls.schema()) assert SchemaCls.schema() == { "title": "ModelBigAuto", "type": "object", "properties": { "bigautofiled": { "title": "Bigautofiled", "type": "integer" } }, }
def test_inheritance(): class ParentModel(models.Model): parent_field = models.CharField() class Meta: app_label = "tests" class ChildModel(ParentModel): child_field = models.CharField() class Meta: app_label = "tests" Schema = create_schema(ChildModel) print(Schema.schema()) # TODO: I guess parentmodel_ptr_id must be skipped assert Schema.schema() == { "title": "ChildModel", "type": "object", "properties": { "id": { "title": "Id", "type": "integer" }, "parent_field": { "title": "Parent Field", "type": "string" }, "parentmodel_ptr_id": { "title": "Parentmodel Ptr", "type": "integer" }, "child_field": { "title": "Child Field", "type": "string" }, }, "required": ["parent_field", "parentmodel_ptr_id", "child_field"], }
def test_with_relations(): # this test basically does full coverage for the case when we skip automatic relation attributes from someapp.models import Category Schema = create_schema(Category) print(Schema.schema()) assert Schema.schema() == { "title": "Category", "type": "object", "properties": { "id": { "title": "Id", "type": "integer" }, "title": { "title": "Title", "maxLength": 100, "type": "string" }, }, "required": ["title"], }
def test_all_fields(): # test all except relational field class AllFields(models.Model): bigintegerfield = models.BigIntegerField() binaryfield = models.BinaryField() booleanfield = models.BooleanField() charfield = models.CharField() commaseparatedintegerfield = models.CommaSeparatedIntegerField() datefield = models.DateField() datetimefield = models.DateTimeField() decimalfield = models.DecimalField() durationfield = models.DurationField() emailfield = models.EmailField() filefield = models.FileField() filepathfield = models.FilePathField() floatfield = models.FloatField() genericipaddressfield = models.GenericIPAddressField() ipaddressfield = models.IPAddressField() imagefield = models.ImageField() integerfield = models.IntegerField() nullbooleanfield = models.NullBooleanField() positiveintegerfield = models.PositiveIntegerField() positivesmallintegerfield = models.PositiveSmallIntegerField() slugfield = models.SlugField() smallintegerfield = models.SmallIntegerField() textfield = models.TextField() timefield = models.TimeField() urlfield = models.URLField() uuidfield = models.UUIDField() class Meta: app_label = "tests" SchemaCls = create_schema(AllFields) # print(SchemaCls.schema()) assert SchemaCls.schema() == { "title": "AllFields", "type": "object", "properties": { "id": { "title": "Id", "type": "integer" }, "bigintegerfield": { "title": "Bigintegerfield", "type": "integer" }, "binaryfield": { "title": "Binaryfield", "type": "string", "format": "binary", }, "booleanfield": { "title": "Booleanfield", "type": "boolean" }, "charfield": { "title": "Charfield", "type": "string" }, "commaseparatedintegerfield": { "title": "Commaseparatedintegerfield", "type": "string", }, "datefield": { "title": "Datefield", "type": "string", "format": "date" }, "datetimefield": { "title": "Datetimefield", "type": "string", "format": "date-time", }, "decimalfield": { "title": "Decimalfield", "type": "number" }, "durationfield": { "title": "Durationfield", "type": "number", "format": "time-delta", }, "emailfield": { "title": "Emailfield", "maxLength": 254, "type": "string" }, "filefield": { "title": "Filefield", "type": "string" }, "filepathfield": { "title": "Filepathfield", "type": "string" }, "floatfield": { "title": "Floatfield", "type": "number" }, "genericipaddressfield": { "title": "Genericipaddressfield", "type": "string", "format": "ipvanyaddress", }, "ipaddressfield": { "title": "Ipaddressfield", "type": "string", "format": "ipvanyaddress", }, "imagefield": { "title": "Imagefield", "type": "string" }, "integerfield": { "title": "Integerfield", "type": "integer" }, "nullbooleanfield": { "title": "Nullbooleanfield", "type": "boolean" }, "positiveintegerfield": { "title": "Positiveintegerfield", "type": "integer", }, "positivesmallintegerfield": { "title": "Positivesmallintegerfield", "type": "integer", }, "slugfield": { "title": "Slugfield", "type": "string" }, "smallintegerfield": { "title": "Smallintegerfield", "type": "integer" }, "textfield": { "title": "Textfield", "type": "string" }, "timefield": { "title": "Timefield", "type": "string", "format": "time" }, "urlfield": { "title": "Urlfield", "type": "string" }, "uuidfield": { "title": "Uuidfield", "type": "string", "format": "uuid" }, }, "required": [ "bigintegerfield", "binaryfield", "booleanfield", "charfield", "commaseparatedintegerfield", "datefield", "datetimefield", "decimalfield", "durationfield", "emailfield", "filefield", "filepathfield", "floatfield", "genericipaddressfield", "ipaddressfield", "imagefield", "integerfield", "nullbooleanfield", "positiveintegerfield", "positivesmallintegerfield", "slugfield", "smallintegerfield", "textfield", "timefield", "urlfield", "uuidfield", ], }
def test_fields_exclude(): class SampleModel(models.Model): f1 = models.CharField() f2 = models.CharField() f3 = models.CharField() class Meta: app_label = "tests" Schema1 = create_schema(SampleModel, fields=["f1", "f2"]) print(Schema1.schema()) assert Schema1.schema() == { "title": "SampleModel", "type": "object", "properties": { "f1": { "title": "F1", "type": "string" }, "f2": { "title": "F2", "type": "string" }, }, "required": ["f1", "f2"], } Schema2 = create_schema(SampleModel, fields=["f3", "f2"]) print(Schema2.schema()) assert Schema2.schema() == { "title": "SampleModel", "type": "object", "properties": { "f3": { "title": "F3", "type": "string" }, "f2": { "title": "F2", "type": "string" }, }, "required": ["f3", "f2"], } Schema3 = create_schema(SampleModel, exclude=["f3"]) print(Schema3.schema()) assert Schema3.schema() == { "title": "SampleModel", "type": "object", "properties": { "id": { "title": "Id", "type": "integer" }, "f1": { "title": "F1", "type": "string" }, "f2": { "title": "F2", "type": "string" }, }, "required": ["f1", "f2"], }
class TestSchema(Schema): data1: create_schema(TestModelDuplicate, fields=["field1"]) # noqa: F821 data2: create_schema(TestModelDuplicate, fields=["field2"]) # noqa: F821
import datetime from typing import Dict, Any, List import pytz from ninja import Schema from ninja.orm import create_schema from backend.models import Notes, Files from tayf_auth.models import CustomUser UserSchema = create_schema(CustomUser) NoteSchema = create_schema(Notes) UserUpdateSchema = create_schema(CustomUser, exclude=[ 'id', 'last_login', 'last_logged_in', 'date_joined', 'groups', 'user_permissions' ]) class NoteCreateSchema(Schema): subject: str note: str user_id: int alarm_at: str = str(datetime.datetime.now(tz=pytz.UTC).isoformat()) status: int class FileSchema(Schema): file: str
def test_relational(): class Related(models.Model): charfield = models.CharField() class Meta: app_label = "tests" class TestModel(models.Model): manytomanyfield = models.ManyToManyField(Related) onetoonefield = models.OneToOneField(Related, on_delete=models.CASCADE) foreignkey = models.ForeignKey(Related, on_delete=models.SET_NULL, null=True) class Meta: app_label = "tests" SchemaCls = create_schema(TestModel, name="TestSchema") print(SchemaCls.schema()) assert SchemaCls.schema() == { "title": "TestSchema", "type": "object", "properties": { "id": { "title": "Id", "type": "integer" }, "onetoonefield_id": { "title": "Onetoonefield", "type": "integer" }, "foreignkey_id": { "title": "Foreignkey", "type": "integer" }, "manytomanyfield": { "title": "Manytomanyfield", "type": "array", "items": { "type": "integer" }, }, }, "required": ["onetoonefield_id", "manytomanyfield"], } SchemaClsDeep = create_schema(TestModel, name="TestSchemaDeep", depth=1) print(SchemaClsDeep.schema()) assert SchemaClsDeep.schema() == { "title": "TestSchemaDeep", "type": "object", "properties": { "id": { "title": "Id", "type": "integer" }, "onetoonefield": { "title": "Onetoonefield", "allOf": [{ "$ref": "#/definitions/Related" }], }, "foreignkey": { "title": "Foreignkey", "allOf": [{ "$ref": "#/definitions/Related" }], }, "manytomanyfield": { "title": "Manytomanyfield", "type": "array", "items": { "$ref": "#/definitions/Related" }, }, }, "required": ["onetoonefield", "manytomanyfield"], "definitions": { "Related": { "title": "Related", "type": "object", "properties": { "id": { "title": "Id", "type": "integer" }, "charfield": { "title": "Charfield", "type": "string" }, }, "required": ["charfield"], } }, }
from typing import Any, Dict from ninja import Schema from ninja.orm import create_schema from tayf_auth import models UserAuthSchema = create_schema( models.CustomUser, fields=['id', 'email', 'first_name', 'last_name', 'sex']) UserProfileSchema = create_schema( models.CustomUser, fields=['email', 'first_name', 'sex', 'last_name']) EditProfileResponseSchema = create_schema( models.CustomUser, fields=['email', 'first_name', 'last_name']) class AccessTokenSchema(Schema): access_token: str class ErrorMessage(Schema): errors: Dict[str, Any] class MailConfirmedSchema(Schema): result: str class LoginSchema(Schema): username: str
from ninja import Router from typing import List from django.shortcuts import get_object_or_404 from livros.models import Livros from ninja.orm import create_schema from uuid import UUID router = Router() # Na entrada, o id será criado automáticamente LivrosSchemaIn = create_schema(Livros, exclude=["id"]) # Na saída, o id deve ser mostrado LivrosSchemaOut = create_schema(Livros) @router.post("") def registrar_livro(request, event: LivrosSchemaIn): Livros.objects.create(**event.dict()) return event @router.get("", response=List[LivrosSchemaOut]) def listar_livros(request): return list(Livros.objects.all()) @router.get("/{id}", response=LivrosSchemaIn) def lista_livro_id(request, id: UUID): return get_object_or_404(Livros, id=UUID)
from typing import List from datetime import datetime from datetime import date from ninja import Schema from ninja.orm import create_schema from . import models # UserSchema = create_schema(User, depth=1, fields=['id','username','first_name','last_name', 'groups']) UserSchema = create_schema(models.User, depth=1, fields=['id', 'email', 'phone', 'school_id']) # UserCreateSchemaIn = create_schema(models.User, fields=['email','phone','password']) class UserCreateSchemaIn(Schema): email: str phone: str password: str UserCreateSchemaOut = create_schema( models.User, depth=1, fields=['id', 'email', 'phone', 'school_id']) # UserForLessonSchema = create_schema(models.User, fields=['id']) class UserForLessonSchema(Schema): id: int UserUpdateSchemaIn = create_schema(models.User,
from django.shortcuts import render, get_object_or_404 # Create your views here. from typing import List, Dict from ninja import NinjaAPI, Schema from ninja.security import django_auth from users.models import User from .models import Entry from ninja.orm import create_schema # ninja_api = NinjaAPI(auth=django_auth, csrf=True) ninja_api = NinjaAPI(title="Entry API") EntryIn = create_schema(Entry, name='EntryIn', fields=['text', 'number']) EntryOut = create_schema(Entry, name='EntryOut') class Entries(Schema): # name: 'Entries' entries: List[EntryOut] columns: List[Dict] # Dict entry_form_fields: Dict UserOut = create_schema(User, name='UserOut', fields=['first_name', 'entries'], depth=1)
from ninja import Router from typing import List from django.shortcuts import get_object_or_404 from app.models import Cliente, Categoria, Imovel, Venda from ninja.orm import create_schema router = Router() # Na entrada, o id será criado automáticamente ClienteSchemaIn = create_schema(Cliente, exclude=["id"]) CategoriaSchemaIn = create_schema(Categoria, exclude=["id"]) ImovelSchemaIn = create_schema(Imovel, exclude=["id"]) VendaSchemaIn = create_schema(Venda, exclude=["id"]) # Na saída, o id deve ser mostrado ClienteSchemaOut = create_schema(Cliente) CategoriaSchemaOut = create_schema(Categoria) ImovelSchemaOut = create_schema(Imovel) VendaSchemaOut = create_schema(Venda) @router.post("/cliente") def registrar_cliente(request, event: ClienteSchemaIn): Cliente.objects.create(**event.dict()) return event @router.get("/cliente", response=List[ClienteSchemaOut]) def listar_clientes(request): return list(Cliente.objects.all()) @router.get("/cliente/{id}", response=ClienteSchemaIn)