Skip to content

Built-in Types

string

The string type is used to store text values.

Example:

{
    "title": "StringModel",
    "type": "object",
    "properties": {
        "name": {
            "type": "string"
        },
        "country": {
            "type": "string",
            "default": "USA"
        }
    },
    "required": []
}

In this example we defined two properties name and country, both with string type.

from models.user.string_model import StringModel

instance_1 = StringModel(name="Name 1", country="GB")
instance_2 = StringModel(name="Name 2")

Note

The default value that we pass for country property is a string value as well.

number

The number type is used to store any number values (integers and floats).

Example:

{
    "title": "NumberModel",
    "type": "object",
    "properties": {
        "count": {
            "type": "number",
            "default": 0
        },
        "temperature": {
            "type": "number",
            "default": 38.8
        }
    },
    "required": []
}

Here, we defined count and temperature properties with number type.

from models.user.number_model import NumberModel

instance = NumberModel(count=10)
instance.temperature = 40.1

Note

The default values for count and temperature properties are also specified as numbers.

Note

The number values are always stored as float values in the database. So, it means, when you get the data from the database, you will get a float value even if you stored the integer number.

boolean

The boolean type is used to store boolean values.

Example:

{
    "title": "BooleanModel",
    "type": "object",
    "properties": {
        "is_active": {
            "type": "boolean"
        },
        "is_superuser": {
            "type": "boolean",
            "default": false
        }
    },
    "required": []
}

In this example, we defined is_active and is_superuser properties with boolean type.

from models.user.boolean_model import BooleanModel

instance = BooleanModel(is_active=True)

print(instance.is_active)  # True
print(instance.is_superuser)  # False

Note

The default value for is_superuser property is boolean value as well.

array

The array type is used to store an ordered list of values. When you define an array property you also need to define the type of items in the array.

Example:

{
    "title": "ArrayModel",
    "type": "object",
    "properties": {
        "tags": {
            "type": "array",
            "items": {
                "type": "string"
            }
        },
        "numbers": {
            "type": "array",
            "items": {
                "type": "number"
            }
        }
    },
    "required": []
}

In this example, we defined tags and numbers properties with array type.

from models.user.array_model import ArrayModel

instance = ArrayModel(tags=["tag 1", "tag 2"], numbers=[1, 2, 3])

Note

The type of the elements in your array must correspond to the type you specified in the schema.

Complex nested arrays

AMSDAL allows for complex nested type definition using array.

Here are several examples:

{
    "title": "ArrayNestedModel",
    "type": "object",
    "properties": {
        "nested_items": {
            "type": "array",
            "items": {
                "type": "dictionary",
                "items": {
                    "key": {
                        "type": "string"
                    },
                    "value": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    } 
                }
            }
        }
    },
    "required": []
}

In the example above, the nested_items property has a complex nested type. When the model class is generated, this property will be defined as nested_items: list[dict[str, list[str]]].

from models.user.array_nested_model import ArrayNestedModel

instance = ArrayNestedModel(
    nested_items=[
        {"key 1": ["value 1", "value 2"]},
        {"key 2": ["value 3"]}
    ]
)

Note

You need to make sure the types of your array elements correspond to the type you specified in the schema.

Another example of complex nested type definition:

{
    "title": "ArrayNestedModel",
    "type": "object",
    "properties": {
        "nested_items": {
            "type": "array",
            "items": {
                "type": "dictionary",
                "items": {
                    "key": {
                        "type": "string"
                    },
                    "value": {
                        "type": "array",
                        "items": {
                            "type": "dictionary",
                            "items": {
                                "key": {
                                    "type": "string"
                                },
                                "value": {
                                    "type": "string"
                                } 
                            }
                        }
                    } 
                }
            }
        }
    },
    "required": []
}

In this example, the nested_items property has complex nested type. When the model class is generated, this property will be defined as nested_items: list[dict[str, list[dict[str, str]]]].

from models.user.array_nested_model import ArrayNestedModel

instance = ArrayNestedModel(
    nested_items=[
        {"key 1": [{"key 1.1": "value 1.1"}, {"key 1.2": "value 1.2"}]},
        {"key 2": [{"key 2.1": "value 2.1"}]}
    ]
)

Note

You need to make sure the types of your array elements correspond to the type you specified in the schema.

It's also possible to define any other model name as a type of the *array element:

{
    "title": "ArrayPersonModel",
    "type": "object",
    "properties": {
        "persons": {
            "type": "array",
            "items": {
                "type": "Person"
            }
        }
    },
    "required": []
}

Here, we defined the persons property that has type array of Person model.

from models.user.people import Person
from models.user.array_person_model import ArrayPersonModel

bob = Person.objects.get(name='Bob').execute()
john = Person.objects.get(name='John').execute()

instance = ArrayPersonModel(
    persons=[
        bob,
        john,
    ],
)

Warning

Currently, it's not possible to filter by elements for the array type using QuerySet.

dictionary

The dictionary type is used to store dictionary (map) of values. When you define a dictionary property you also define the types of the dictionaries keys and values.

Example:

{
    "title": "DictionaryModel",
    "type": "object",
    "properties": {
        "data": {
            "type": "dictionary",
            "items": {
                "key": {
                    "type": "string"
                },
                "value": {
                    "type": "number"
                }
            }
        }
    },
    "required": []
}

In the example above, we defined data property with dictionary type and specified the string type for key and number type for value.

from models.user.dictionary_model import DictionaryModel

instance = DictionaryModel(data={"key 1": 10, "key 2": 20})

print(instance.data)  # {"key 1": 10, "key 2": 20}

Warning

The dictionary's key type must be immutable type. You cannot define array or dictionary as the key type

Complex nested dictionaries

The dictionary type allows for complex nested structures where the value may be another dictionary or array type

{
    "title": "DictionaryNestedModel",
    "type": "object",
    "properties": {
        "data": {
            "type": "dictionary",
            "items": {
                "key": {
                    "type": "string"
                },
                "value": {
                    "type": "dictionary",
                    "items": {
                        "key": {
                            "type": "number"
                        },
                        "value": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        }
    },
    "required": []
}

In this example, the data property has dict[str, dict[float, list[str]]] type

from models.user.dictionary_nested_model import DictionaryNestedModel

instance = DictionaryNestedModel(
    data={
        "key 1": {
            10: ["val 1"],
            20: ["val 2", "val 3"]
        },
        "key 2": {
            100: ["val 4"]
        }
    }
)

AMSDAL also supports any other model as either a key or value type

For example:

{
    "title": "DictionaryPersonModel",
    "type": "object",
    "properties": {
        "person_age": {
            "type": "dictionary",
            "items": {
                "key": {
                    "type": "Person"
                },
                "value": {
                    "type": "number"
                }
            }
        }
    },
    "required": []
}
from models.user.people import Person
from models.user.dictionary_person_model import DictionaryPersonModel

bob = Person.objects.get(name='Bob').execute()
john = Person.objects.get(name='John').execute()

instance = DictionaryPersonModel(
    person_age={
        bob: 18,
        john: 21,
    },
)

Warning

Currently, it isn't possible to filter by elements for the dictionary type using QuerySet.

binary

The binary type allows to store binary data (bytes).

Example:

{
    "title": "BinaryModel",
    "type": "object",
    "properties": {
        "data": {
            "type": "binary"
        }
    },
    "required": []
}
from models.user.binary_model import BinaryModel

instance = BinaryModel(data=b'binary data')

Note

JSON does not support binary data, therefore you cannot specify the default value for binary type.

anything

The anything type allows to store any structure of data. For example, it can be used when you have the array or dictionary with elements/values of different types, e.g [10, "value", bool].

Example:

{
    "title": "AnythingModel",
    "type": "object",
    "properties": {
        "meta": {
            "type": "dictionary",
            "items": {
                "key": {
                    "type": "string"
                },
                "value": {
                    "type": "anything"
                }
            }
        },
        "data": {
            "type": "anything"
        }
    },
    "required": []
}

In this example we defined two properties: meta and data. The meta property has dictionary type with the string type for keys and anything type for values. The data property has anything type.

from models.user.anything_model import AnythingModel

instance = AnythingModel(
    meta={
        "key 1": 10,
        "key 2": "value 1",
        "key 3": True
    },
    data=[100, "value 2", False]
)

Note

anything means any valid python or JSON serializable data.

Warning

Try to avoid to use anything type for your properties, as it does not allow for any validation. So, while it is possible to store any kind of data, you cannot guarantee the quality of the data nor use any kind of filtering by this property in QuerySet.

File

The File type is built-in model that extends binary type and provides ability to store files in the database. It has the following properties:

Property name Type Description
filename string The name of file.
data binary The binary data of file.
size number The size of file in bytes.
mimetype Custom Property This is custom readonly property, that is calculated automatically based on the filename.

Example:

{
    "title": "FileModel",
    "type": "object",
    "properties": {
        "data": {
            "type": "File"
        }
    },
    "required": []
}
from models.user.file_model import FileModel
from models.core.file import File

instance = FileModel(
    data=File(
        filename='my_file.txt',
        data=b'my binary content',
    ),
)

Info

The File model's data property stores data as bytes, although, it's possible to use string values as well, in which case it will convert the string data into bytes by encoding it to utf-8.

base64 encoded strings are also supported where a base64 encoded string passed as a value will be decoded and stored the original binary data.

from models.core.file import File

instance = File(
    filename='my_file.txt',
    data='Y29udGVudA==',
)

print(instance.data)  # b'content'

The File provides several useful methods.

from_file

File.from_file(file_or_path: Path | BinaryIO) static-method

This provides you ability to create the File instance directly from File object or file path.

from pathlib import Path
from models.core.file import File

# From File object
with open('my-file.txt', 'rb') as f:
    instance_from_file = File.from_file(f)

# From file path
file_path: Path = Path('my-file.txt')
instance_from_path = File.from_file(file_path)

Note

The file path should be a pathlib.Path instance. The file object can be any BinaryIO object.

to_file

File.to_file(file_or_path: Path | BinaryIO) instance-method

This method provides ability to save the file to the file system.

from pathlib import Path
from models.core.file import File

stored_file = File.obects.get(filename='my-file.txt').execute()

# To File object
with open('my-file.txt', 'wb') as f:
    stored_file.to_file(f)

# to file path
file_path: Path = Path('my-file.txt')
stored_file.to_file(file_path)

Note

This method should be executed on the instance of the File model.

└── 📁 models
    └── 📁 my_model
        ├── 📁 hooks
        ├── 📄 model.json
        └── 📁 fixtures
            ├── 📄 fixture_example.csv
            └── 📄 fixture_example.json