Skip to content

Dynamically Generating a Schema

Under the hood, ModelSchema uses the create_schema function. This is a more advanced (and less safe) approach — use it with caution.

create_schema

Django Ninja ships with a helper function create_schema:

def create_schema(
    model, # django model
    name = "", # name for the generated class, if empty model names is used
    depth = 0, # if > 0 schema will also be created for the nested ForeignKeys and Many2Many (with the provided depth of lookup)
    fields: list[str] = None, # if passed - ONLY these fields will added to schema
    exclude: list[str] = None, # if passed - these fields will be excluded from schema
    optional_fields: list[str] | str = None, # if passed - these fields will not be required on schema (use '__all__' to mark ALL fields required)
    custom_fields: list[tuple(str, Any, Any)] = None, # if passed - this will override default field types (or add new fields)
)

Take a look at this example:

from django.contrib.auth.models import User
from ninja.orm import create_schema

UserSchema = create_schema(User)

# Will create schema like this:
# 
# class UserSchema(Schema):
#     id: int
#     username: str
#     first_name: str
#     last_name: str
#     password: str
#     last_login: datetime
#     is_superuser: bool
#     email: str
#     ... and the rest

Warning

By default, create_schema builds the schema using all model fields. This may lead to accidental exposure of unwanted data (such as the hashed password, in the example above).
Always use the fields or exclude argument to explicitly define the list of attributes.

Using fields

UserSchema = create_schema(User, fields=['id', 'username'])

# Will create schema like this:
# 
# class UserSchema(Schema):
#     id: int
#     username: str

Using exclude

UserSchema = create_schema(User, exclude=[
    'password', 'last_login', 'is_superuser', 'is_staff', 'groups', 'user_permissions']
)

# Will create schema without excluded fields:
# 
# class UserSchema(Schema):
#    id: int
#    username: str
#    first_name: str
#    last_name: str
#    email: str
#    is_active: bool
#    date_joined: datetime

Using depth

The depth argument allows you to introspect Django model related fields (foreign keys, one-to-one, many-to-many).

UserSchema = create_schema(User, depth=1, fields=['username', 'groups'])

# Will create the following schema:
#
# class UserSchema(Schema):
#    username: str
#    groups: List[Group]

Note that here groups becomes List[Group] — the many-to-many field was introspected 1 level deep and a schema was created for groups as well:

class Group(Schema):
    id: int
    name: str
    permissions: List[int]

Done

Continue to the next chapter! Overriding Pydantic Configuration

Comments


本文总阅读量次