diff --git a/docs/api/exceptions.md b/docs/api/exceptions.md
new file mode 100644
index 0000000..e9bb2b6
--- /dev/null
+++ b/docs/api/exceptions.md
@@ -0,0 +1,96 @@
+
+# exceptions
+
+Gathers all exceptions thrown by ormar.
+
+
+## AsyncOrmException Objects
+
+```python
+class AsyncOrmException(Exception)
+```
+
+Base ormar Exception
+
+
+## ModelDefinitionError Objects
+
+```python
+class ModelDefinitionError(AsyncOrmException)
+```
+
+Raised for errors related to the model definition itself:
+
+* setting @property_field on method with arguments other than func(self)
+* defining a Field without required parameters
+* defining a model with more than one primary_key
+* defining a model without primary_key
+* setting primary_key column as pydantic_only
+
+
+## ModelError Objects
+
+```python
+class ModelError(AsyncOrmException)
+```
+
+Raised for initialization of model with non-existing field keyword.
+
+
+## NoMatch Objects
+
+```python
+class NoMatch(AsyncOrmException)
+```
+
+Raised for database queries that has no matching result (empty result).
+
+
+## MultipleMatches Objects
+
+```python
+class MultipleMatches(AsyncOrmException)
+```
+
+Raised for database queries that should return one row (i.e. get, first etc.)
+but has multiple matching results in response.
+
+
+## QueryDefinitionError Objects
+
+```python
+class QueryDefinitionError(AsyncOrmException)
+```
+
+Raised for errors in query definition:
+
+* using contains or icontains filter with instance of the Model
+* using Queryset.update() without filter and setting each flag to True
+* using Queryset.delete() without filter and setting each flag to True
+
+
+## RelationshipInstanceError Objects
+
+```python
+class RelationshipInstanceError(AsyncOrmException)
+```
+
+
+## ModelPersistenceError Objects
+
+```python
+class ModelPersistenceError(AsyncOrmException)
+```
+
+Raised for update of models without primary_key set (cannot retrieve from db)
+or for saving a model with relation to unsaved model (cannot extract fk value).
+
+
+## SignalDefinitionError Objects
+
+```python
+class SignalDefinitionError(AsyncOrmException)
+```
+
+Raised when non callable receiver is passed as signal callback.
+
diff --git a/docs/api/fields/base-field.md b/docs/api/fields/base-field.md
new file mode 100644
index 0000000..64fa4fb
--- /dev/null
+++ b/docs/api/fields/base-field.md
@@ -0,0 +1,292 @@
+
+# fields.base
+
+
+## BaseField Objects
+
+```python
+class BaseField(FieldInfo)
+```
+
+BaseField serves as a parent class for all basic Fields in ormar.
+It keeps all common parameters available for all fields as well as
+set of useful functions.
+
+All values are kept as class variables, ormar Fields are never instantiated.
+Subclasses pydantic.FieldInfo to keep the fields related
+to pydantic field types like ConstrainedStr
+
+
+#### \_\_type\_\_
+
+
+#### related\_name
+
+
+#### column\_type
+
+
+#### constraints
+
+
+#### name
+
+
+#### alias
+
+
+#### primary\_key
+
+
+#### autoincrement
+
+
+#### nullable
+
+
+#### index
+
+
+#### unique
+
+
+#### pydantic\_only
+
+
+#### virtual
+
+
+#### choices
+
+
+#### to
+
+
+#### through
+
+
+#### default
+
+
+#### server\_default
+
+
+#### is\_valid\_uni\_relation
+
+```python
+ | @classmethod
+ | is_valid_uni_relation(cls) -> bool
+```
+
+Checks if field is a relation definition but only for ForeignKey relation,
+so excludes ManyToMany fields, as well as virtual ForeignKey
+(second side of FK relation).
+
+Is used to define if a field is a db ForeignKey column that
+should be saved/populated when dealing with internal/own
+Model columns only.
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+#### get\_alias
+
+```python
+ | @classmethod
+ | get_alias(cls) -> str
+```
+
+Used to translate Model column names to database column names during db queries.
+
+**Returns**:
+
+`(str)`: returns custom database column name if defined by user,
+otherwise field name in ormar/pydantic
+
+
+#### is\_valid\_field\_info\_field
+
+```python
+ | @classmethod
+ | is_valid_field_info_field(cls, field_name: str) -> bool
+```
+
+Checks if field belongs to pydantic FieldInfo
+- used during setting default pydantic values.
+Excludes defaults and alias as they are populated separately
+(defaults) or not at all (alias)
+
+**Arguments**:
+
+- `field_name (str)`: field name of BaseFIeld
+
+**Returns**:
+
+`(bool)`: True if field is present on pydantic.FieldInfo
+
+
+#### convert\_to\_pydantic\_field\_info
+
+```python
+ | @classmethod
+ | convert_to_pydantic_field_info(cls, allow_null: bool = False) -> FieldInfo
+```
+
+Converts a BaseField into pydantic.FieldInfo
+that is later easily processed by pydantic.
+Used in an ormar Model Metaclass.
+
+**Arguments**:
+
+- `allow_null (bool)`: flag if the default value can be None
+or if it should be populated by pydantic Undefined
+
+**Returns**:
+
+`(pydantic.FieldInfo)`: actual instance of pydantic.FieldInfo with all needed fields populated
+
+
+#### default\_value
+
+```python
+ | @classmethod
+ | default_value(cls, use_server: bool = False) -> Optional[FieldInfo]
+```
+
+Returns a FieldInfo instance with populated default
+(static) or default_factory (function).
+If the field is a autoincrement primary key the default is None.
+Otherwise field have to has either default, or default_factory populated.
+
+If all default conditions fail None is returned.
+
+Used in converting to pydantic FieldInfo.
+
+**Arguments**:
+
+- `use_server (bool)`: flag marking if server_default should be
+treated as default value, default False
+
+**Returns**:
+
+`(Optional[pydantic.FieldInfo])`: returns a call to pydantic.Field
+which is returning a FieldInfo instance
+
+
+#### get\_default
+
+```python
+ | @classmethod
+ | get_default(cls, use_server: bool = False) -> Any
+```
+
+Return default value for a field.
+If the field is Callable the function is called and actual result is returned.
+Used to populate default_values for pydantic Model in ormar Model Metaclass.
+
+**Arguments**:
+
+- `use_server (bool)`: flag marking if server_default should be
+treated as default value, default False
+
+**Returns**:
+
+`(Any)`: default value for the field if set, otherwise implicit None
+
+
+#### has\_default
+
+```python
+ | @classmethod
+ | has_default(cls, use_server: bool = True) -> bool
+```
+
+Checks if the field has default value set.
+
+**Arguments**:
+
+- `use_server (bool)`: flag marking if server_default should be
+treated as default value, default False
+
+**Returns**:
+
+`(bool)`: result of the check if default value is set
+
+
+#### is\_auto\_primary\_key
+
+```python
+ | @classmethod
+ | is_auto_primary_key(cls) -> bool
+```
+
+Checks if field is first a primary key and if it,
+it's than check if it's set to autoincrement.
+Autoincrement primary_key is nullable/optional.
+
+**Returns**:
+
+`(bool)`: result of the check for primary key and autoincrement
+
+
+#### construct\_constraints
+
+```python
+ | @classmethod
+ | construct_constraints(cls) -> List
+```
+
+Converts list of ormar constraints into sqlalchemy ForeignKeys.
+Has to be done dynamically as sqlalchemy binds ForeignKey to the table.
+And we need a new ForeignKey for subclasses of current model
+
+**Returns**:
+
+`(List[sqlalchemy.schema.ForeignKey])`: List of sqlalchemy foreign keys - by default one.
+
+
+#### get\_column
+
+```python
+ | @classmethod
+ | get_column(cls, name: str) -> sqlalchemy.Column
+```
+
+Returns definition of sqlalchemy.Column used in creation of sqlalchemy.Table.
+Populates name, column type constraints, as well as a number of parameters like
+primary_key, index, unique, nullable, default and server_default.
+
+**Arguments**:
+
+- `name (str)`: name of the db column - used if alias is not set
+
+**Returns**:
+
+`(sqlalchemy.Column)`: actual definition of the database column as sqlalchemy requires.
+
+
+#### expand\_relationship
+
+```python
+ | @classmethod
+ | expand_relationship(cls, value: Any, child: Union["Model", "NewBaseModel"], to_register: bool = True, relation_name: str = None) -> Any
+```
+
+Function overwritten for relations, in basic field the value is returned as is.
+For relations the child model is first constructed (if needed),
+registered in relation and returned.
+For relation fields the value can be a pk value (Any type of field),
+dict (from Model) or actual instance/list of a "Model".
+
+**Arguments**:
+
+- `value (Any)`: a Model field value, returned untouched for non relation fields.
+- `child (Union["Model", "NewBaseModel"])`: a child Model to register
+- `to_register (bool)`: flag if the relation should be set in RelationshipManager
+
+**Returns**:
+
+`(Any)`: returns untouched value for normal fields, expands only for relations
+
diff --git a/docs/api/fields/decorators.md b/docs/api/fields/decorators.md
new file mode 100644
index 0000000..28e052c
--- /dev/null
+++ b/docs/api/fields/decorators.md
@@ -0,0 +1,28 @@
+
+# decorators.property\_field
+
+
+#### property\_field
+
+```python
+property_field(func: Callable) -> Union[property, Callable]
+```
+
+Decorator to set a property like function on Model to be exposed
+as field in dict() and fastapi response.
+Although you can decorate a @property field like this and this will work,
+mypy validation will complain about this.
+Note that "fields" exposed like this do not go through validation.
+
+**Raises**:
+
+- `ModelDefinitionError`: if method has any other argument than self.
+
+**Arguments**:
+
+- `func (Callable)`: decorated function to be exposed
+
+**Returns**:
+
+`(Union[property, Callable])`: decorated function passed in func param, with set __property_field__ = True
+
diff --git a/docs/api/fields/foreign-key.md b/docs/api/fields/foreign-key.md
new file mode 100644
index 0000000..f274e37
--- /dev/null
+++ b/docs/api/fields/foreign-key.md
@@ -0,0 +1,267 @@
+
+# fields.foreign\_key
+
+
+#### create\_dummy\_instance
+
+```python
+create_dummy_instance(fk: Type["Model"], pk: Any = None) -> "Model"
+```
+
+Ormar never returns you a raw data.
+So if you have a related field that has a value populated
+it will construct you a Model instance out of it.
+
+Creates a "fake" instance of passed Model from pk value.
+The instantiated Model has only pk value filled.
+To achieve this __pk_only__ flag has to be passed as it skips the validation.
+
+If the nested related Models are required they are set with -1 as pk value.
+
+**Arguments**:
+
+- `fk (Model class)`: class of the related Model to which instance should be constructed
+- `pk (Any)`: value of the primary_key column
+
+**Returns**:
+
+`(Model)`: Model instance populated with only pk
+
+
+#### create\_dummy\_model
+
+```python
+create_dummy_model(base_model: Type["Model"], pk_field: Type[Union[BaseField, "ForeignKeyField", "ManyToManyField"]]) -> Type["BaseModel"]
+```
+
+Used to construct a dummy pydantic model for type hints and pydantic validation.
+Populates only pk field and set it to desired type.
+
+**Arguments**:
+
+- `base_model (Model class)`: class of target dummy model
+- `pk_field (Type[Union[BaseField, "ForeignKeyField", "ManyToManyField"]])`: ormar Field to be set on pydantic Model
+
+**Returns**:
+
+`(pydantic.BaseModel)`: constructed dummy model
+
+
+## UniqueColumns Objects
+
+```python
+class UniqueColumns(UniqueConstraint)
+```
+
+Subclass of sqlalchemy.UniqueConstraint.
+Used to avoid importing anything from sqlalchemy by user.
+
+
+## ForeignKeyConstraint Objects
+
+```python
+@dataclass
+class ForeignKeyConstraint()
+```
+
+Internal container to store ForeignKey definitions used later
+to produce sqlalchemy.ForeignKeys
+
+
+#### name
+
+
+#### ondelete
+
+
+#### onupdate
+
+
+#### ForeignKey
+
+```python
+ForeignKey(to: Type["Model"], *, name: str = None, unique: bool = False, nullable: bool = True, related_name: str = None, virtual: bool = False, onupdate: str = None, ondelete: str = None, **kwargs: Any, ,) -> Any
+```
+
+Despite a name it's a function that returns constructed ForeignKeyField.
+This function is actually used in model declaration (as ormar.ForeignKey(ToModel)).
+
+Accepts number of relation setting parameters as well as all BaseField ones.
+
+**Arguments**:
+
+- `to (Model class)`: target related ormar Model
+- `name (str)`: name of the database field - later called alias
+- `unique (bool)`: parameter passed to sqlalchemy.ForeignKey, unique flag
+- `nullable (bool)`: marks field as optional/ required
+- `related_name (str)`: name of reversed FK relation populated for you on to model
+- `virtual (bool)`: marks if relation is virtual.
+It is for reversed FK and auto generated FK on through model in Many2Many relations.
+- `onupdate (str)`: parameter passed to sqlalchemy.ForeignKey.
+How to treat child rows on update of parent (the one where FK is defined) model.
+- `ondelete (str)`: parameter passed to sqlalchemy.ForeignKey.
+How to treat child rows on delete of parent (the one where FK is defined) model.
+- `kwargs (Any)`: all other args to be populated by BaseField
+
+**Returns**:
+
+`(ForeignKeyField)`: ormar ForeignKeyField with relation to selected model
+
+
+## ForeignKeyField Objects
+
+```python
+class ForeignKeyField(BaseField)
+```
+
+Actual class returned from ForeignKey function call and stored in model_fields.
+
+
+#### to
+
+
+#### name
+
+
+#### related\_name
+
+
+#### virtual
+
+
+#### \_extract\_model\_from\_sequence
+
+```python
+ | @classmethod
+ | _extract_model_from_sequence(cls, value: List, child: "Model", to_register: bool, relation_name: str) -> List["Model"]
+```
+
+Takes a list of Models and registers them on parent.
+Registration is mutual, so children have also reference to parent.
+
+Used in reverse FK relations.
+
+**Arguments**:
+
+- `value (List)`: list of Model
+- `child (Model)`: child/ related Model
+- `to_register (bool)`: flag if the relation should be set in RelationshipManager
+
+**Returns**:
+
+`(List["Model"])`: list (if needed) registered Models
+
+
+#### \_register\_existing\_model
+
+```python
+ | @classmethod
+ | _register_existing_model(cls, value: "Model", child: "Model", to_register: bool, relation_name: str) -> "Model"
+```
+
+Takes already created instance and registers it for parent.
+Registration is mutual, so children have also reference to parent.
+
+Used in reverse FK relations and normal FK for single models.
+
+**Arguments**:
+
+- `value (Model)`: already instantiated Model
+- `child (Model)`: child/ related Model
+- `to_register (bool)`: flag if the relation should be set in RelationshipManager
+
+**Returns**:
+
+`(Model)`: (if needed) registered Model
+
+
+#### \_construct\_model\_from\_dict
+
+```python
+ | @classmethod
+ | _construct_model_from_dict(cls, value: dict, child: "Model", to_register: bool, relation_name: str) -> "Model"
+```
+
+Takes a dictionary, creates a instance and registers it for parent.
+If dictionary contains only one field and it's a pk it is a __pk_only__ model.
+Registration is mutual, so children have also reference to parent.
+
+Used in normal FK for dictionaries.
+
+**Arguments**:
+
+- `value (dict)`: dictionary of a Model
+- `child (Model)`: child/ related Model
+- `to_register (bool)`: flag if the relation should be set in RelationshipManager
+
+**Returns**:
+
+`(Model)`: (if needed) registered Model
+
+
+#### \_construct\_model\_from\_pk
+
+```python
+ | @classmethod
+ | _construct_model_from_pk(cls, value: Any, child: "Model", to_register: bool, relation_name: str) -> "Model"
+```
+
+Takes a pk value, creates a dummy instance and registers it for parent.
+Registration is mutual, so children have also reference to parent.
+
+Used in normal FK for dictionaries.
+
+**Arguments**:
+
+- `value (Any)`: value of a related pk / fk column
+- `child (Model)`: child/ related Model
+- `to_register (bool)`: flag if the relation should be set in RelationshipManager
+
+**Returns**:
+
+`(Model)`: (if needed) registered Model
+
+
+#### register\_relation
+
+```python
+ | @classmethod
+ | register_relation(cls, model: "Model", child: "Model", relation_name: str) -> None
+```
+
+Registers relation between parent and child in relation manager.
+Relation manager is kep on each model (different instance).
+
+Used in Metaclass and sometimes some relations are missing
+(i.e. cloned Models in fastapi might miss one).
+
+**Arguments**:
+
+- `model (Model class)`: parent model (with relation definition)
+- `child (Model class)`: child model
+
+
+#### expand\_relationship
+
+```python
+ | @classmethod
+ | expand_relationship(cls, value: Any, child: Union["Model", "NewBaseModel"], to_register: bool = True, relation_name: str = None) -> Optional[Union["Model", List["Model"]]]
+```
+
+For relations the child model is first constructed (if needed),
+registered in relation and returned.
+For relation fields the value can be a pk value (Any type of field),
+dict (from Model) or actual instance/list of a "Model".
+
+Selects the appropriate constructor based on a passed value.
+
+**Arguments**:
+
+- `value (Any)`: a Model field value, returned untouched for non relation fields.
+- `child (Union["Model", "NewBaseModel"])`: a child Model to register
+- `to_register (bool)`: flag if the relation should be set in RelationshipManager
+
+**Returns**:
+
+`(Optional[Union["Model", List["Model"]]])`: returns a Model or a list of Models
+
diff --git a/docs/api/fields/many-to-many.md b/docs/api/fields/many-to-many.md
new file mode 100644
index 0000000..d950ee6
--- /dev/null
+++ b/docs/api/fields/many-to-many.md
@@ -0,0 +1,59 @@
+
+# fields.many\_to\_many
+
+
+#### REF\_PREFIX
+
+
+#### ManyToMany
+
+```python
+ManyToMany(to: Type["Model"], through: Type["Model"], *, name: str = None, unique: bool = False, virtual: bool = False, **kwargs: Any) -> Any
+```
+
+Despite a name it's a function that returns constructed ManyToManyField.
+This function is actually used in model declaration
+(as ormar.ManyToMany(ToModel, through=ThroughModel)).
+
+Accepts number of relation setting parameters as well as all BaseField ones.
+
+**Arguments**:
+
+- `to (Model class)`: target related ormar Model
+- `through (Model class)`: through model for m2m relation
+- `name (str)`: name of the database field - later called alias
+- `unique (bool)`: parameter passed to sqlalchemy.ForeignKey, unique flag
+- `virtual (bool)`: marks if relation is virtual.
+It is for reversed FK and auto generated FK on through model in Many2Many relations.
+- `kwargs (Any)`: all other args to be populated by BaseField
+
+**Returns**:
+
+`(ManyToManyField)`: ormar ManyToManyField with m2m relation to selected model
+
+
+## ManyToManyField Objects
+
+```python
+class ManyToManyField(ForeignKeyField, ormar.QuerySetProtocol, ormar.RelationProtocol)
+```
+
+Actual class returned from ManyToMany function call and stored in model_fields.
+
+
+#### through
+
+
+#### default\_target\_field\_name
+
+```python
+ | @classmethod
+ | default_target_field_name(cls) -> str
+```
+
+Returns default target model name on through model.
+
+**Returns**:
+
+`(str)`: name of the field
+
diff --git a/docs/api/fields/model-fields.md b/docs/api/fields/model-fields.md
new file mode 100644
index 0000000..0744438
--- /dev/null
+++ b/docs/api/fields/model-fields.md
@@ -0,0 +1,514 @@
+
+# fields.model\_fields
+
+
+#### is\_field\_nullable
+
+```python
+is_field_nullable(nullable: Optional[bool], default: Any, server_default: Any, pydantic_only: Optional[bool]) -> bool
+```
+
+Checks if the given field should be nullable/ optional based on parameters given.
+
+**Arguments**:
+
+- `nullable (Optional[bool])`: flag explicit setting a column as nullable
+- `default (Any)`: value or function to be called as default in python
+- `server_default (Any)`: function to be called as default by sql server
+- `pydantic_only (Optional[bool])`: flag if fields should not be included in the sql table
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+#### is\_auto\_primary\_key
+
+```python
+is_auto_primary_key(primary_key: bool, autoincrement: bool) -> bool
+```
+
+Checks if field is an autoincrement pk -> if yes it's optional.
+
+**Arguments**:
+
+- `primary_key (bool)`: flag if field is a pk field
+- `autoincrement (bool)`: flag if field should be autoincrement
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+## ModelFieldFactory Objects
+
+```python
+class ModelFieldFactory()
+```
+
+Default field factory that construct Field classes and populated their values.
+
+
+#### \_bases
+
+
+#### \_type
+
+
+#### \_\_new\_\_
+
+```python
+ | __new__(cls, *args: Any, **kwargs: Any) -> Type[BaseField]
+```
+
+
+#### get\_column\_type
+
+```python
+ | @classmethod
+ | get_column_type(cls, **kwargs: Any) -> Any
+```
+
+Return proper type of db column for given field type.
+Accepts required and optional parameters that each column type accepts.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pairs of sqlalchemy options
+
+**Returns**:
+
+`(sqlalchemy Column)`: initialized column with proper options
+
+
+#### validate
+
+```python
+ | @classmethod
+ | validate(cls, **kwargs: Any) -> None
+```
+
+Used to validate if all required parameters on a given field type are set.
+
+**Arguments**:
+
+- `kwargs (Any)`: all params passed during construction
+
+
+## String Objects
+
+```python
+class String(ModelFieldFactory, str)
+```
+
+String field factory that construct Field classes and populated their values.
+
+
+#### \_type
+
+
+#### \_\_new\_\_
+
+```python
+ | __new__(cls, *, allow_blank: bool = True, strip_whitespace: bool = False, min_length: int = None, max_length: int = None, curtail_length: int = None, regex: str = None, **kwargs: Any) -> Type[BaseField]
+```
+
+
+#### get\_column\_type
+
+```python
+ | @classmethod
+ | get_column_type(cls, **kwargs: Any) -> Any
+```
+
+Return proper type of db column for given field type.
+Accepts required and optional parameters that each column type accepts.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pairs of sqlalchemy options
+
+**Returns**:
+
+`(sqlalchemy Column)`: initialized column with proper options
+
+
+#### validate
+
+```python
+ | @classmethod
+ | validate(cls, **kwargs: Any) -> None
+```
+
+Used to validate if all required parameters on a given field type are set.
+
+**Arguments**:
+
+- `kwargs (Any)`: all params passed during construction
+
+
+## Integer Objects
+
+```python
+class Integer(ModelFieldFactory, int)
+```
+
+Integer field factory that construct Field classes and populated their values.
+
+
+#### \_type
+
+
+#### \_\_new\_\_
+
+```python
+ | __new__(cls, *, minimum: int = None, maximum: int = None, multiple_of: int = None, **kwargs: Any) -> Type[BaseField]
+```
+
+
+#### get\_column\_type
+
+```python
+ | @classmethod
+ | get_column_type(cls, **kwargs: Any) -> Any
+```
+
+Return proper type of db column for given field type.
+Accepts required and optional parameters that each column type accepts.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pairs of sqlalchemy options
+
+**Returns**:
+
+`(sqlalchemy Column)`: initialized column with proper options
+
+
+## Text Objects
+
+```python
+class Text(ModelFieldFactory, str)
+```
+
+Text field factory that construct Field classes and populated their values.
+
+
+#### \_type
+
+
+#### \_\_new\_\_
+
+```python
+ | __new__(cls, *, allow_blank: bool = True, strip_whitespace: bool = False, **kwargs: Any) -> Type[BaseField]
+```
+
+
+#### get\_column\_type
+
+```python
+ | @classmethod
+ | get_column_type(cls, **kwargs: Any) -> Any
+```
+
+Return proper type of db column for given field type.
+Accepts required and optional parameters that each column type accepts.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pairs of sqlalchemy options
+
+**Returns**:
+
+`(sqlalchemy Column)`: initialized column with proper options
+
+
+## Float Objects
+
+```python
+class Float(ModelFieldFactory, float)
+```
+
+Float field factory that construct Field classes and populated their values.
+
+
+#### \_type
+
+
+#### \_\_new\_\_
+
+```python
+ | __new__(cls, *, minimum: float = None, maximum: float = None, multiple_of: int = None, **kwargs: Any) -> Type[BaseField]
+```
+
+
+#### get\_column\_type
+
+```python
+ | @classmethod
+ | get_column_type(cls, **kwargs: Any) -> Any
+```
+
+Return proper type of db column for given field type.
+Accepts required and optional parameters that each column type accepts.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pairs of sqlalchemy options
+
+**Returns**:
+
+`(sqlalchemy Column)`: initialized column with proper options
+
+
+## DateTime Objects
+
+```python
+class DateTime(ModelFieldFactory, datetime.datetime)
+```
+
+DateTime field factory that construct Field classes and populated their values.
+
+
+#### \_type
+
+
+#### get\_column\_type
+
+```python
+ | @classmethod
+ | get_column_type(cls, **kwargs: Any) -> Any
+```
+
+Return proper type of db column for given field type.
+Accepts required and optional parameters that each column type accepts.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pairs of sqlalchemy options
+
+**Returns**:
+
+`(sqlalchemy Column)`: initialized column with proper options
+
+
+## Date Objects
+
+```python
+class Date(ModelFieldFactory, datetime.date)
+```
+
+Date field factory that construct Field classes and populated their values.
+
+
+#### \_type
+
+
+#### get\_column\_type
+
+```python
+ | @classmethod
+ | get_column_type(cls, **kwargs: Any) -> Any
+```
+
+Return proper type of db column for given field type.
+Accepts required and optional parameters that each column type accepts.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pairs of sqlalchemy options
+
+**Returns**:
+
+`(sqlalchemy Column)`: initialized column with proper options
+
+
+## Time Objects
+
+```python
+class Time(ModelFieldFactory, datetime.time)
+```
+
+Time field factory that construct Field classes and populated their values.
+
+
+#### \_type
+
+
+#### get\_column\_type
+
+```python
+ | @classmethod
+ | get_column_type(cls, **kwargs: Any) -> Any
+```
+
+Return proper type of db column for given field type.
+Accepts required and optional parameters that each column type accepts.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pairs of sqlalchemy options
+
+**Returns**:
+
+`(sqlalchemy Column)`: initialized column with proper options
+
+
+## JSON Objects
+
+```python
+class JSON(ModelFieldFactory, pydantic.Json)
+```
+
+JSON field factory that construct Field classes and populated their values.
+
+
+#### \_type
+
+
+#### get\_column\_type
+
+```python
+ | @classmethod
+ | get_column_type(cls, **kwargs: Any) -> Any
+```
+
+Return proper type of db column for given field type.
+Accepts required and optional parameters that each column type accepts.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pairs of sqlalchemy options
+
+**Returns**:
+
+`(sqlalchemy Column)`: initialized column with proper options
+
+
+## BigInteger Objects
+
+```python
+class BigInteger(Integer, int)
+```
+
+BigInteger field factory that construct Field classes and populated their values.
+
+
+#### \_type
+
+
+#### \_\_new\_\_
+
+```python
+ | __new__(cls, *, minimum: int = None, maximum: int = None, multiple_of: int = None, **kwargs: Any) -> Type[BaseField]
+```
+
+
+#### get\_column\_type
+
+```python
+ | @classmethod
+ | get_column_type(cls, **kwargs: Any) -> Any
+```
+
+Return proper type of db column for given field type.
+Accepts required and optional parameters that each column type accepts.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pairs of sqlalchemy options
+
+**Returns**:
+
+`(sqlalchemy Column)`: initialized column with proper options
+
+
+## Decimal Objects
+
+```python
+class Decimal(ModelFieldFactory, decimal.Decimal)
+```
+
+Decimal field factory that construct Field classes and populated their values.
+
+
+#### \_type
+
+
+#### \_\_new\_\_
+
+```python
+ | __new__(cls, *, minimum: float = None, maximum: float = None, multiple_of: int = None, precision: int = None, scale: int = None, max_digits: int = None, decimal_places: int = None, **kwargs: Any) -> Type[BaseField]
+```
+
+
+#### get\_column\_type
+
+```python
+ | @classmethod
+ | get_column_type(cls, **kwargs: Any) -> Any
+```
+
+Return proper type of db column for given field type.
+Accepts required and optional parameters that each column type accepts.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pairs of sqlalchemy options
+
+**Returns**:
+
+`(sqlalchemy Column)`: initialized column with proper options
+
+
+#### validate
+
+```python
+ | @classmethod
+ | validate(cls, **kwargs: Any) -> None
+```
+
+Used to validate if all required parameters on a given field type are set.
+
+**Arguments**:
+
+- `kwargs (Any)`: all params passed during construction
+
+
+## UUID Objects
+
+```python
+class UUID(ModelFieldFactory, uuid.UUID)
+```
+
+UUID field factory that construct Field classes and populated their values.
+
+
+#### \_type
+
+
+#### \_\_new\_\_
+
+```python
+ | __new__(cls, *, uuid_format: str = "hex", **kwargs: Any) -> Type[BaseField]
+```
+
+
+#### get\_column\_type
+
+```python
+ | @classmethod
+ | get_column_type(cls, **kwargs: Any) -> Any
+```
+
+Return proper type of db column for given field type.
+Accepts required and optional parameters that each column type accepts.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pairs of sqlalchemy options
+
+**Returns**:
+
+`(sqlalchemy Column)`: initialized column with proper options
+
diff --git a/docs/api/index.md b/docs/api/index.md
new file mode 100644
index 0000000..2081c16
--- /dev/null
+++ b/docs/api/index.md
@@ -0,0 +1,16 @@
+Contains documentation of the `ormar` internal API.
+
+Note that this is a technical part of the documentation intended for `ormar` contributors.
+
+!!!note
+ For completeness as of now even the internal and special methods are documented and exposed in API docs.
+
+!!!warning
+ The current API docs version is a beta and not all methods are documented,
+ also some of redundant items are included since it was partially auto generated.
+
+!!!danger
+ Ormar is still under development, and the **internals can change at any moment**.
+
+ You shouldn't rely even on the "public" methods if they are not documented in the
+ normal part of the docs.
\ No newline at end of file
diff --git a/docs/api/models/helpers/models.md b/docs/api/models/helpers/models.md
new file mode 100644
index 0000000..ddeb85d
--- /dev/null
+++ b/docs/api/models/helpers/models.md
@@ -0,0 +1,64 @@
+
+# models.helpers.models
+
+
+#### populate\_default\_options\_values
+
+```python
+populate_default_options_values(new_model: Type["Model"], model_fields: Dict) -> None
+```
+
+Sets all optional Meta values to it's defaults
+and set model_fields that were already previously extracted.
+
+Here should live all options that are not overwritten/set for all models.
+
+Current options are:
+* constraints = []
+* abstract = False
+
+**Arguments**:
+
+- `new_model (Model class)`: newly constructed Model
+- `model_fields (Union[Dict[str, type], Dict])`:
+
+
+#### extract\_annotations\_and\_default\_vals
+
+```python
+extract_annotations_and_default_vals(attrs: Dict) -> Tuple[Dict, Dict]
+```
+
+Extracts annotations from class namespace dict and triggers
+extraction of ormar model_fields.
+
+**Arguments**:
+
+- `attrs (Dict)`: namespace of the class created
+
+**Returns**:
+
+`(Tuple[Dict, Dict])`: namespace of the class updated, dict of extracted model_fields
+
+
+#### validate\_related\_names\_in\_relations
+
+```python
+validate_related_names_in_relations(model_fields: Dict, new_model: Type["Model"]) -> None
+```
+
+Performs a validation of relation_names in relation fields.
+If multiple fields are leading to the same related model
+only one can have empty related_name param
+(populated by default as model.name.lower()+'s').
+Also related_names have to be unique for given related model.
+
+**Raises**:
+
+- `ModelDefinitionError`: if validation of related_names fail
+
+**Arguments**:
+
+- `model_fields (Dict[str, ormar.Field])`: dictionary of declared ormar model fields
+- `new_model (Model class)`:
+
diff --git a/docs/api/models/helpers/pydantic.md b/docs/api/models/helpers/pydantic.md
new file mode 100644
index 0000000..8b38eaf
--- /dev/null
+++ b/docs/api/models/helpers/pydantic.md
@@ -0,0 +1,122 @@
+
+# models.helpers.pydantic
+
+
+#### create\_pydantic\_field
+
+```python
+create_pydantic_field(field_name: str, model: Type["Model"], model_field: Type[ManyToManyField]) -> None
+```
+
+Registers pydantic field on through model that leads to passed model
+and is registered as field_name passed.
+
+Through model is fetched from through attributed on passed model_field.
+
+**Arguments**:
+
+- `field_name (str)`: field name to register
+- `model (Model class)`: type of field to register
+- `model_field (ManyToManyField class)`: relation field from which through model is extracted
+
+
+#### get\_pydantic\_field
+
+```python
+get_pydantic_field(field_name: str, model: Type["Model"]) -> "ModelField"
+```
+
+Extracts field type and if it's required from Model model_fields by passed
+field_name. Returns a pydantic field with type of field_name field type.
+
+**Arguments**:
+
+- `field_name (str)`: field name to fetch from Model and name of pydantic field
+- `model (Model class)`: type of field to register
+
+**Returns**:
+
+`(pydantic.ModelField)`: newly created pydantic field
+
+
+#### populate\_default\_pydantic\_field\_value
+
+```python
+populate_default_pydantic_field_value(ormar_field: Type[BaseField], field_name: str, attrs: dict) -> dict
+```
+
+Grabs current value of the ormar Field in class namespace
+(so the default_value declared on ormar model if set)
+and converts it to pydantic.FieldInfo
+that pydantic is able to extract later.
+
+On FieldInfo there are saved all needed params like max_length of the string
+and other constraints that pydantic can use to build
+it's own field validation used by ormar.
+
+**Arguments**:
+
+- `ormar_field (ormar Field)`: field to convert
+- `field_name (str)`: field to convert name
+- `attrs (Dict)`: current class namespace
+
+**Returns**:
+
+`(Dict)`: updated namespace dict
+
+
+#### populate\_pydantic\_default\_values
+
+```python
+populate_pydantic_default_values(attrs: Dict) -> Tuple[Dict, Dict]
+```
+
+Extracts ormar fields from annotations (deprecated) and from namespace
+dictionary of the class. Fields declared on model are all subclasses of the
+BaseField class.
+
+Trigger conversion of ormar field into pydantic FieldInfo, which has all needed
+paramaters saved.
+
+Overwrites the annotations of ormar fields to corresponding types declared on
+ormar fields (constructed dynamically for relations).
+Those annotations are later used by pydantic to construct it's own fields.
+
+**Arguments**:
+
+- `attrs (Dict)`: current class namespace
+
+**Returns**:
+
+`(Tuple[Dict, Dict])`: namespace of the class updated, dict of extracted model_fields
+
+
+#### get\_pydantic\_base\_orm\_config
+
+```python
+get_pydantic_base_orm_config() -> Type[BaseConfig]
+```
+
+Returns empty pydantic Config with orm_mode set to True.
+
+**Returns**:
+
+`(pydantic Config)`: empty default config with orm_mode set.
+
+
+#### get\_potential\_fields
+
+```python
+get_potential_fields(attrs: Dict) -> Dict
+```
+
+Gets all the fields in current class namespace that are Fields.
+
+**Arguments**:
+
+- `attrs (Dict)`: current class namespace
+
+**Returns**:
+
+`(Dict)`: extracted fields that are ormar Fields
+
diff --git a/docs/api/models/helpers/relations.md b/docs/api/models/helpers/relations.md
new file mode 100644
index 0000000..83b30a3
--- /dev/null
+++ b/docs/api/models/helpers/relations.md
@@ -0,0 +1,154 @@
+
+# models.helpers.relations
+
+
+#### alias\_manager
+
+
+#### register\_relation\_on\_build
+
+```python
+register_relation_on_build(new_model: Type["Model"], field_name: str) -> None
+```
+
+Registers ForeignKey relation in alias_manager to set a table_prefix.
+Registration include also reverse relation side to be able to join both sides.
+
+Relation is registered by model name and relation field name to allow for multiple
+relations between two Models that needs to have different
+aliases for proper sql joins.
+
+**Arguments**:
+
+- `new_model (Model class)`: constructed model
+- `field_name (str)`: name of the related field
+
+
+#### register\_many\_to\_many\_relation\_on\_build
+
+```python
+register_many_to_many_relation_on_build(new_model: Type["Model"], field: Type[ManyToManyField], field_name: str) -> None
+```
+
+Registers connection between through model and both sides of the m2m relation.
+Registration include also reverse relation side to be able to join both sides.
+
+Relation is registered by model name and relation field name to allow for multiple
+relations between two Models that needs to have different
+aliases for proper sql joins.
+
+By default relation name is a model.name.lower().
+
+**Arguments**:
+
+- `field_name (str)`: name of the relation key
+- `new_model (Model class)`: model on which m2m field is declared
+- `field (ManyToManyField class)`: relation field
+
+
+#### expand\_reverse\_relationships
+
+```python
+expand_reverse_relationships(model: Type["Model"]) -> None
+```
+
+Iterates through model_fields of given model and verifies if all reverse
+relation have been populated on related models.
+
+If the reverse relation has not been set before it's set here.
+
+**Arguments**:
+
+- `model (Model class)`: model on which relation should be checked and registered
+
+
+#### register\_reverse\_model\_fields
+
+```python
+register_reverse_model_fields(model: Type["Model"], child: Type["Model"], related_name: str, model_field: Type["ForeignKeyField"]) -> None
+```
+
+Registers reverse ForeignKey field on related model.
+By default it's name.lower()+'s' of the model on which relation is defined.
+
+But if the related_model name is provided it's registered with that name.
+Autogenerated reverse fields also set related_name to the original field name.
+
+**Arguments**:
+
+- `model (Model class)`: related model on which reverse field should be defined
+- `child (Model class)`: parent model with relation definition
+- `related_name (str)`: name by which reverse key should be registered
+- `model_field (relation Field)`: original relation ForeignKey field
+
+
+#### register\_relation\_in\_alias\_manager
+
+```python
+register_relation_in_alias_manager(new_model: Type["Model"], field: Type[ForeignKeyField], field_name: str) -> None
+```
+
+Registers the relation (and reverse relation) in alias manager.
+The m2m relations require registration of through model between
+actual end models of the relation.
+
+Delegates the actual registration to:
+m2m - register_many_to_many_relation_on_build
+fk - register_relation_on_build
+
+**Arguments**:
+
+- `new_model (Model class)`: model on which relation field is declared
+- `field (ForeignKey or ManyToManyField class)`: relation field
+- `field_name (str)`: name of the relation key
+
+
+#### verify\_related\_name\_dont\_duplicate
+
+```python
+verify_related_name_dont_duplicate(child: Type["Model"], parent_model: Type["Model"], related_name: str) -> None
+```
+
+Verifies whether the used related_name (regardless of the fact if user defined or
+auto generated) is already used on related model, but is connected with other model
+than the one that we connect right now.
+
+**Raises**:
+
+- `ModelDefinitionError`: if name is already used but lead to different related
+model
+
+**Arguments**:
+
+- `child (ormar.models.metaclass.ModelMetaclass)`: related Model class
+- `parent_model (ormar.models.metaclass.ModelMetaclass)`: parent Model class
+- `related_name ()`:
+
+**Returns**:
+
+`(None)`: None
+
+
+#### reverse\_field\_not\_already\_registered
+
+```python
+reverse_field_not_already_registered(child: Type["Model"], child_model_name: str, parent_model: Type["Model"]) -> bool
+```
+
+Checks if child is already registered in parents pydantic fields.
+
+**Raises**:
+
+- `ModelDefinitionError`: if related name is already used but lead to different
+related model
+
+**Arguments**:
+
+- `child (ormar.models.metaclass.ModelMetaclass)`: related Model class
+- `child_model_name (str)`: related_name of the child if provided
+- `parent_model (ormar.models.metaclass.ModelMetaclass)`: parent Model class
+
+**Returns**:
+
+`(bool)`: result of the check
+
diff --git a/docs/api/models/helpers/sqlalchemy.md b/docs/api/models/helpers/sqlalchemy.md
new file mode 100644
index 0000000..87b6d0e
--- /dev/null
+++ b/docs/api/models/helpers/sqlalchemy.md
@@ -0,0 +1,145 @@
+
+# models.helpers.sqlalchemy
+
+
+#### adjust\_through\_many\_to\_many\_model
+
+```python
+adjust_through_many_to_many_model(model: Type["Model"], child: Type["Model"], model_field: Type[ManyToManyField]) -> None
+```
+
+Registers m2m relation on through model.
+Sets ormar.ForeignKey from through model to both child and parent models.
+Sets sqlalchemy.ForeignKey to both child and parent models.
+Sets pydantic fields with child and parent model types.
+
+**Arguments**:
+
+- `model (Model class)`: model on which relation is declared
+- `child (Model class)`: model to which m2m relation leads
+- `model_field (ManyToManyField)`: relation field defined in parent model
+
+
+#### create\_and\_append\_m2m\_fk
+
+```python
+create_and_append_m2m_fk(model: Type["Model"], model_field: Type[ManyToManyField]) -> None
+```
+
+Registers sqlalchemy Column with sqlalchemy.ForeignKey leadning to the model.
+
+Newly created field is added to m2m relation through model Meta columns and table.
+
+**Arguments**:
+
+- `model (Model class)`: Model class to which FK should be created
+- `model_field (ManyToManyField field)`: field with ManyToMany relation
+
+
+#### check\_pk\_column\_validity
+
+```python
+check_pk_column_validity(field_name: str, field: BaseField, pkname: Optional[str]) -> Optional[str]
+```
+
+Receives the field marked as primary key and verifies if the pkname
+was not already set (only one allowed per model) and if field is not marked
+as pydantic_only as it needs to be a database field.
+
+**Raises**:
+
+- `ModelDefintionError`: if pkname already set or field is pydantic_only
+
+**Arguments**:
+
+- `field_name (str)`: name of field
+- `field (BaseField)`: ormar.Field
+- `pkname (Optional[str])`: already set pkname
+
+**Returns**:
+
+`(str)`: name of the field that should be set as pkname
+
+
+#### sqlalchemy\_columns\_from\_model\_fields
+
+```python
+sqlalchemy_columns_from_model_fields(model_fields: Dict, new_model: Type["Model"]) -> Tuple[Optional[str], List[sqlalchemy.Column]]
+```
+
+Iterates over declared on Model model fields and extracts fields that
+should be treated as database fields.
+
+If the model is empty it sets mandatory id field as primary key
+(used in through models in m2m relations).
+
+Triggers a validation of relation_names in relation fields. If multiple fields
+are leading to the same related model only one can have empty related_name param.
+Also related_names have to be unique.
+
+Trigger validation of primary_key - only one and required pk can be set,
+cannot be pydantic_only.
+
+Append fields to columns if it's not pydantic_only,
+virtual ForeignKey or ManyToMany field.
+
+**Raises**:
+
+- `ModelDefinitionError`: if validation of related_names fail,
+or pkname validation fails.
+
+**Arguments**:
+
+- `model_fields (Dict[str, ormar.Field])`: dictionary of declared ormar model fields
+- `new_model (Model class)`:
+
+**Returns**:
+
+`(Tuple[Optional[str], List[sqlalchemy.Column]])`: pkname, list of sqlalchemy columns
+
+
+#### populate\_meta\_tablename\_columns\_and\_pk
+
+```python
+populate_meta_tablename_columns_and_pk(name: str, new_model: Type["Model"]) -> Type["Model"]
+```
+
+Sets Model tablename if it's not already set in Meta.
+Default tablename if not present is class name lower + s (i.e. Bed becomes -> beds)
+
+Checks if Model's Meta have pkname and columns set.
+If not calls the sqlalchemy_columns_from_model_fields to populate
+columns from ormar.fields definitions.
+
+**Raises**:
+
+- `ModelDefinitionError`: if pkname is not present raises ModelDefinitionError.
+Each model has to have pk.
+
+**Arguments**:
+
+- `name (str)`: name of the current Model
+- `new_model (ormar.models.metaclass.ModelMetaclass)`: currently constructed Model
+
+**Returns**:
+
+`(ormar.models.metaclass.ModelMetaclass)`: Model with populated pkname and columns in Meta
+
+
+#### populate\_meta\_sqlalchemy\_table\_if\_required
+
+```python
+populate_meta_sqlalchemy_table_if_required(meta: "ModelMeta") -> None
+```
+
+Constructs sqlalchemy table out of columns and parameters set on Meta class.
+It populates name, metadata, columns and constraints.
+
+**Arguments**:
+
+- `meta (Model class Meta)`: Meta class of the Model without sqlalchemy table constructed
+
+**Returns**:
+
+`(Model class)`: class with populated Meta.table
+
diff --git a/docs/api/models/mixins/alias-mixin.md b/docs/api/models/mixins/alias-mixin.md
new file mode 100644
index 0000000..c3a48a4
--- /dev/null
+++ b/docs/api/models/mixins/alias-mixin.md
@@ -0,0 +1,90 @@
+
+# models.mixins.alias\_mixin
+
+
+## AliasMixin Objects
+
+```python
+class AliasMixin()
+```
+
+Used to translate field names into database column names.
+
+
+#### get\_column\_alias
+
+```python
+ | @classmethod
+ | get_column_alias(cls, field_name: str) -> str
+```
+
+Returns db alias (column name in db) for given ormar field.
+For fields without alias field name is returned.
+
+**Arguments**:
+
+- `field_name (str)`: name of the field to get alias from
+
+**Returns**:
+
+`(str)`: alias (db name) if set, otherwise passed name
+
+
+#### get\_column\_name\_from\_alias
+
+```python
+ | @classmethod
+ | get_column_name_from_alias(cls, alias: str) -> str
+```
+
+Returns ormar field name for given db alias (column name in db).
+If field do not have alias it's returned as is.
+
+**Arguments**:
+
+- `alias (str)`:
+
+**Returns**:
+
+`(str)`: field name if set, otherwise passed alias (db name)
+
+
+#### translate\_columns\_to\_aliases
+
+```python
+ | @classmethod
+ | translate_columns_to_aliases(cls, new_kwargs: Dict) -> Dict
+```
+
+Translates dictionary of model fields changing field names into aliases.
+If field has no alias the field name remains intact.
+Only fields present in the dictionary are translated.
+
+**Arguments**:
+
+- `new_kwargs (Dict)`: dict with fields names and their values
+
+**Returns**:
+
+`(Dict)`: dict with aliases and their values
+
+
+#### translate\_aliases\_to\_columns
+
+```python
+ | @classmethod
+ | translate_aliases_to_columns(cls, new_kwargs: Dict) -> Dict
+```
+
+Translates dictionary of model fields changing aliases into field names.
+If field has no alias the alias is already a field name.
+Only fields present in the dictionary are translated.
+
+**Arguments**:
+
+- `new_kwargs (Dict)`: dict with aliases and their values
+
+**Returns**:
+
+`(Dict)`: dict with fields names and their values
+
diff --git a/docs/api/models/mixins/excludable-mixin.md b/docs/api/models/mixins/excludable-mixin.md
new file mode 100644
index 0000000..a4d9c79
--- /dev/null
+++ b/docs/api/models/mixins/excludable-mixin.md
@@ -0,0 +1,206 @@
+
+# models.mixins.excludable\_mixin
+
+
+## ExcludableMixin Objects
+
+```python
+class ExcludableMixin(RelationMixin)
+```
+
+Used to include/exclude given set of fields on models during load and dict() calls.
+
+
+#### get\_child
+
+```python
+ | @staticmethod
+ | get_child(items: Union[Set, Dict, None], key: str = None) -> Union[Set, Dict, None]
+```
+
+Used to get nested dictionaries keys if they exists otherwise returns
+passed items.
+
+**Arguments**:
+
+- `items (Union[Set, Dict, None])`: bag of items to include or exclude
+- `key (str)`: name of the child to extract
+
+**Returns**:
+
+`(Union[Set, Dict, None])`: child extracted from items if exists
+
+
+#### get\_excluded
+
+```python
+ | @staticmethod
+ | get_excluded(exclude: Union[Set, Dict, None], key: str = None) -> Union[Set, Dict, None]
+```
+
+Proxy to ExcludableMixin.get_child for exclusions.
+
+**Arguments**:
+
+- `exclude (Union[Set, Dict, None])`: bag of items to exclude
+- `key (str)`: name of the child to extract
+
+**Returns**:
+
+`(Union[Set, Dict, None])`: child extracted from items if exists
+
+
+#### get\_included
+
+```python
+ | @staticmethod
+ | get_included(include: Union[Set, Dict, None], key: str = None) -> Union[Set, Dict, None]
+```
+
+Proxy to ExcludableMixin.get_child for inclusions.
+
+**Arguments**:
+
+- `include (Union[Set, Dict, None])`: bag of items to include
+- `key (str)`: name of the child to extract
+
+**Returns**:
+
+`(Union[Set, Dict, None])`: child extracted from items if exists
+
+
+#### is\_excluded
+
+```python
+ | @staticmethod
+ | is_excluded(exclude: Union[Set, Dict, None], key: str = None) -> bool
+```
+
+Checks if given key should be excluded on model/ dict.
+
+**Arguments**:
+
+- `exclude (Union[Set, Dict, None])`: bag of items to exclude
+- `key (str)`: name of the child to extract
+
+**Returns**:
+
+`(Union[Set, Dict, None])`: child extracted from items if exists
+
+
+#### is\_included
+
+```python
+ | @staticmethod
+ | is_included(include: Union[Set, Dict, None], key: str = None) -> bool
+```
+
+Checks if given key should be included on model/ dict.
+
+**Arguments**:
+
+- `include (Union[Set, Dict, None])`: bag of items to include
+- `key (str)`: name of the child to extract
+
+**Returns**:
+
+`(Union[Set, Dict, None])`: child extracted from items if exists
+
+
+#### \_populate\_pk\_column
+
+```python
+ | @staticmethod
+ | _populate_pk_column(model: Type["Model"], columns: List[str], use_alias: bool = False) -> List[str]
+```
+
+Adds primary key column/alias (depends on use_alias flag) to list of
+column names that are selected.
+
+**Arguments**:
+
+- `model (Type["Model"])`: model on columns are selected
+- `columns (List[str])`: list of columns names
+- `use_alias (bool)`: flag to set if aliases or field names should be used
+
+**Returns**:
+
+`(List[str])`: list of columns names with pk column in it
+
+
+#### own\_table\_columns
+
+```python
+ | @classmethod
+ | own_table_columns(cls, model: Type["Model"], fields: Optional[Union[Set, Dict]], exclude_fields: Optional[Union[Set, Dict]], use_alias: bool = False) -> List[str]
+```
+
+Returns list of aliases or field names for given model.
+Aliases/names switch is use_alias flag.
+
+If provided only fields included in fields will be returned.
+If provided fields in exclude_fields will be excluded in return.
+
+Primary key field is always added and cannot be excluded (will be added anyway).
+
+**Arguments**:
+
+- `model (Type["Model"])`: model on columns are selected
+- `fields (Optional[Union[Set, Dict]])`: set/dict of fields to include
+- `exclude_fields (Optional[Union[Set, Dict]])`: set/dict of fields to exclude
+- `use_alias (bool)`: flag if aliases or field names should be used
+
+**Returns**:
+
+`(List[str])`: list of column field names or aliases
+
+
+#### \_update\_excluded\_with\_related\_not\_required
+
+```python
+ | @classmethod
+ | _update_excluded_with_related_not_required(cls, exclude: Union["AbstractSetIntStr", "MappingIntStrAny", None], nested: bool = False) -> Union[Set, Dict]
+```
+
+Used during generation of the dict().
+To avoid cyclical references and max recurrence limit nested models have to
+exclude related models that are not mandatory.
+
+For a main model (not nested) only nullable related field names are added to
+exclusion, for nested models all related models are excluded.
+
+**Arguments**:
+
+- `exclude (Union[Set, Dict, None])`: set/dict with fields to exclude
+- `nested (bool)`: flag setting nested models (child of previous one, not main one)
+
+**Returns**:
+
+`(Union[Set, Dict])`: set or dict with excluded fields added.
+
+
+#### get\_names\_to\_exclude
+
+```python
+ | @classmethod
+ | get_names_to_exclude(cls, fields: Optional[Union[Dict, Set]] = None, exclude_fields: Optional[Union[Dict, Set]] = None) -> Set
+```
+
+Returns a set of models field names that should be explicitly excluded
+during model initialization.
+
+Those fields will be set to None to avoid ormar/pydantic setting default
+values on them. They should be returned as None in any case.
+
+Used in parsing data from database rows that construct Models by initializing
+them with dicts constructed from those db rows.
+
+**Arguments**:
+
+- `fields (Optional[Union[Set, Dict]])`: set/dict of fields to include
+- `exclude_fields (Optional[Union[Set, Dict]])`: set/dict of fields to exclude
+
+**Returns**:
+
+`(Set)`: set of field names that should be excluded
+
diff --git a/docs/api/models/mixins/merge-model-mixin.md b/docs/api/models/mixins/merge-model-mixin.md
new file mode 100644
index 0000000..a7ccbd9
--- /dev/null
+++ b/docs/api/models/mixins/merge-model-mixin.md
@@ -0,0 +1,60 @@
+
+# models.mixins.merge\_mixin
+
+
+## MergeModelMixin Objects
+
+```python
+class MergeModelMixin()
+```
+
+Used to merge models instances returned by database,
+but already initialized to ormar Models.keys
+
+Models can duplicate during joins when parent model has multiple child rows,
+in the end all parent (main) models should be unique.
+
+
+#### merge\_instances\_list
+
+```python
+ | @classmethod
+ | merge_instances_list(cls, result_rows: Sequence["Model"]) -> Sequence["Model"]
+```
+
+Merges a list of models into list of unique models.
+
+Models can duplicate during joins when parent model has multiple child rows,
+in the end all parent (main) models should be unique.
+
+**Arguments**:
+
+- `result_rows (List["Model"])`: list of already initialized Models with child models
+populated, each instance is one row in db and some models can duplicate
+
+**Returns**:
+
+`(List["Model"])`: list of merged models where each main model is unique
+
+
+#### merge\_two\_instances
+
+```python
+ | @classmethod
+ | merge_two_instances(cls, one: "Model", other: "Model") -> "Model"
+```
+
+Merges current (other) Model and previous one (one) and returns the current
+Model instance with data merged from previous one.
+
+If needed it's calling itself recurrently and merges also children models.
+
+**Arguments**:
+
+- `one (Model)`: previous model instance
+- `other (Model)`: current model instance
+
+**Returns**:
+
+`(Model)`: current Model instance with data merged from previous one.
+
diff --git a/docs/api/models/mixins/prefetch-query-mixin.md b/docs/api/models/mixins/prefetch-query-mixin.md
new file mode 100644
index 0000000..05d8b8b
--- /dev/null
+++ b/docs/api/models/mixins/prefetch-query-mixin.md
@@ -0,0 +1,100 @@
+
+# models.mixins.prefetch\_mixin
+
+
+## PrefetchQueryMixin Objects
+
+```python
+class PrefetchQueryMixin(RelationMixin)
+```
+
+Used in PrefetchQuery to extract ids and names of models to prefetch.
+
+
+#### get\_clause\_target\_and\_filter\_column\_name
+
+```python
+ | @staticmethod
+ | get_clause_target_and_filter_column_name(parent_model: Type["Model"], target_model: Type["Model"], reverse: bool, related: str) -> Tuple[Type["Model"], str]
+```
+
+Returns Model on which query clause should be performed and name of the column.
+
+**Arguments**:
+
+- `parent_model (Type[Model])`: related model that the relation lead to
+- `target_model (Type[Model])`: model on which query should be perfomed
+- `reverse (bool)`: flag if the relation is reverse
+- `related (str)`: name of the relation field
+
+**Returns**:
+
+`(Tuple[Type[Model], str])`: Model on which query clause should be performed and name of the column
+
+
+#### get\_column\_name\_for\_id\_extraction
+
+```python
+ | @staticmethod
+ | get_column_name_for_id_extraction(parent_model: Type["Model"], reverse: bool, related: str, use_raw: bool) -> str
+```
+
+Returns name of the column that should be used to extract ids from model.
+Depending on the relation side it's either primary key column of parent model
+or field name specified by related parameter.
+
+**Arguments**:
+
+- `parent_model (Type[Model])`: model from which id column should be extracted
+- `reverse (bool)`: flag if the relation is reverse
+- `related (str)`: name of the relation field
+- `use_raw (bool)`: flag if aliases or field names should be used
+
+**Returns**:
+
+`()`:
+
+
+#### get\_related\_field\_name
+
+```python
+ | @classmethod
+ | get_related_field_name(cls, target_field: Type["BaseField"]) -> str
+```
+
+Returns name of the relation field that should be used in prefetch query.
+This field is later used to register relation in prefetch query,
+populate relations dict, and populate nested model in prefetch query.
+
+**Arguments**:
+
+- `target_field (Type[BaseField])`: relation field that should be used in prefetch
+
+**Returns**:
+
+`(str)`: name of the field
+
+
+#### get\_filtered\_names\_to\_extract
+
+```python
+ | @classmethod
+ | get_filtered_names_to_extract(cls, prefetch_dict: Dict) -> List
+```
+
+Returns list of related fields names that should be followed to prefetch related
+models from.
+
+List of models is translated into dict to assure each model is extracted only
+once in one query, that's why this function accepts prefetch_dict not list.
+
+Only relations from current model are returned.
+
+**Arguments**:
+
+- `prefetch_dict (Dict)`: dictionary of fields to extract
+
+**Returns**:
+
+`(List)`: list of fields names to extract
+
diff --git a/docs/api/models/mixins/relation-mixin.md b/docs/api/models/mixins/relation-mixin.md
new file mode 100644
index 0000000..5e94eb9
--- /dev/null
+++ b/docs/api/models/mixins/relation-mixin.md
@@ -0,0 +1,93 @@
+
+# models.mixins.relation\_mixin
+
+
+## RelationMixin Objects
+
+```python
+class RelationMixin()
+```
+
+Used to return relation fields/names etc. from given model
+
+
+#### extract\_db\_own\_fields
+
+```python
+ | @classmethod
+ | extract_db_own_fields(cls) -> Set
+```
+
+Returns only fields that are stored in the own database table, exclude all
+related fields.
+
+**Returns**:
+
+`(Set)`: set of model fields with relation fields excluded
+
+
+#### extract\_related\_fields
+
+```python
+ | @classmethod
+ | extract_related_fields(cls) -> List
+```
+
+Returns List of ormar Fields for all relations declared on a model.
+List is cached in cls._related_fields for quicker access.
+
+**Returns**:
+
+`(List)`: list of related fields
+
+
+#### extract\_related\_names
+
+```python
+ | @classmethod
+ | extract_related_names(cls) -> Set
+```
+
+Returns List of fields names for all relations declared on a model.
+List is cached in cls._related_names for quicker access.
+
+**Returns**:
+
+`(List)`: list of related fields names
+
+
+#### \_extract\_db\_related\_names
+
+```python
+ | @classmethod
+ | _extract_db_related_names(cls) -> Set
+```
+
+Returns only fields that are stored in the own database table, exclude
+related fields that are not stored as foreign keys on given model.
+
+**Returns**:
+
+`(Set)`: set of model fields with non fk relation fields excluded
+
+
+#### \_exclude\_related\_names\_not\_required
+
+```python
+ | @classmethod
+ | _exclude_related_names_not_required(cls, nested: bool = False) -> Set
+```
+
+Returns a set of non mandatory related models field names.
+
+For a main model (not nested) only nullable related field names are returned,
+for nested models all related models are returned.
+
+**Arguments**:
+
+- `nested (bool)`: flag setting nested models (child of previous one, not main one)
+
+**Returns**:
+
+`(Set)`: set of non mandatory related fields
+
diff --git a/docs/api/models/mixins/save-prepare-mixin.md b/docs/api/models/mixins/save-prepare-mixin.md
new file mode 100644
index 0000000..d8c7e57
--- /dev/null
+++ b/docs/api/models/mixins/save-prepare-mixin.md
@@ -0,0 +1,93 @@
+
+# models.mixins.save\_mixin
+
+
+## SavePrepareMixin Objects
+
+```python
+class SavePrepareMixin(RelationMixin, AliasMixin)
+```
+
+Used to prepare models to be saved in database
+
+
+#### prepare\_model\_to\_save
+
+```python
+ | @classmethod
+ | prepare_model_to_save(cls, new_kwargs: dict) -> dict
+```
+
+Combines all preparation methods before saving.
+Removes primary key for if it's nullable or autoincrement pk field,
+and it's set to None.
+Substitute related models with their primary key values as fk column.
+Populates the default values for field with default set and no value.
+Translate columns into aliases (db names).
+
+**Arguments**:
+
+- `new_kwargs (Dict[str, str])`: dictionary of model that is about to be saved
+
+**Returns**:
+
+`(Dict[str, str])`: dictionary of model that is about to be saved
+
+
+#### \_remove\_pk\_from\_kwargs
+
+```python
+ | @classmethod
+ | _remove_pk_from_kwargs(cls, new_kwargs: dict) -> dict
+```
+
+Removes primary key for if it's nullable or autoincrement pk field,
+and it's set to None.
+
+**Arguments**:
+
+- `new_kwargs (Dict[str, str])`: dictionary of model that is about to be saved
+
+**Returns**:
+
+`(Dict[str, str])`: dictionary of model that is about to be saved
+
+
+#### substitute\_models\_with\_pks
+
+```python
+ | @classmethod
+ | substitute_models_with_pks(cls, model_dict: Dict) -> Dict
+```
+
+Receives dictionary of model that is about to be saved and changes all related
+models that are stored as foreign keys to their fk value.
+
+**Arguments**:
+
+- `model_dict (Dict)`: dictionary of model that is about to be saved
+
+**Returns**:
+
+`(Dict)`: dictionary of model that is about to be saved
+
+
+#### populate\_default\_values
+
+```python
+ | @classmethod
+ | populate_default_values(cls, new_kwargs: Dict) -> Dict
+```
+
+Receives dictionary of model that is about to be saved and populates the default
+value on the fields that have the default value set, but no actual value was
+passed by the user.
+
+**Arguments**:
+
+- `new_kwargs (Dict)`: dictionary of model that is about to be saved
+
+**Returns**:
+
+`(Dict)`: dictionary of model that is about to be saved
+
diff --git a/docs/api/models/model-metaclass.md b/docs/api/models/model-metaclass.md
new file mode 100644
index 0000000..b9e372a
--- /dev/null
+++ b/docs/api/models/model-metaclass.md
@@ -0,0 +1,340 @@
+
+# models.metaclass
+
+
+#### PARSED\_FIELDS\_KEY
+
+
+#### CONFIG\_KEY
+
+
+## ModelMeta Objects
+
+```python
+class ModelMeta()
+```
+
+Class used for type hinting.
+Users can subclass this one for convenience but it's not required.
+The only requirement is that ormar.Model has to have inner class with name Meta.
+
+
+#### tablename
+
+
+#### table
+
+
+#### metadata
+
+
+#### database
+
+
+#### columns
+
+
+#### constraints
+
+
+#### pkname
+
+
+#### model\_fields
+
+
+#### alias\_manager
+
+
+#### property\_fields
+
+
+#### signals
+
+
+#### abstract
+
+
+#### check\_if\_field\_has\_choices
+
+```python
+check_if_field_has_choices(field: Type[BaseField]) -> bool
+```
+
+Checks if given field has choices populated.
+A if it has one, a validator for this field needs to be attached.
+
+**Arguments**:
+
+- `field (BaseField)`: ormar field to check
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+#### choices\_validator
+
+```python
+choices_validator(cls: Type["Model"], values: Dict[str, Any]) -> Dict[str, Any]
+```
+
+Validator that is attached to pydantic model pre root validators.
+Validator checks if field value is in field.choices list.
+
+**Raises**:
+
+- `ValueError`: if field value is outside of allowed choices.
+
+**Arguments**:
+
+- `cls (Model class)`: constructed class
+- `values (Dict[str, Any])`: dictionary of field values (pydantic side)
+
+**Returns**:
+
+`(Dict[str, Any])`: values if pass validation, otherwise exception is raised
+
+
+#### populate\_choices\_validators
+
+```python
+populate_choices_validators(model: Type["Model"]) -> None
+```
+
+Checks if Model has any fields with choices set.
+If yes it adds choices validation into pre root validators.
+
+**Arguments**:
+
+- `model (Model class)`: newly constructed Model
+
+
+#### add\_cached\_properties
+
+```python
+add_cached_properties(new_model: Type["Model"]) -> None
+```
+
+Sets cached properties for both pydantic and ormar models.
+
+Quick access fields are fields grabbed in getattribute to skip all checks.
+
+Related fields and names are populated to None as they can change later.
+When children models are constructed they can modify parent to register itself.
+
+All properties here are used as "cache" to not recalculate them constantly.
+
+**Arguments**:
+
+- `new_model (Model class)`: newly constructed Model
+
+
+#### meta\_field\_not\_set
+
+```python
+meta_field_not_set(model: Type["Model"], field_name: str) -> bool
+```
+
+Checks if field with given name is already present in model.Meta.
+Then check if it's set to something truthful
+(in practice meaning not None, as it's non or ormar Field only).
+
+**Arguments**:
+
+- `model (Model class)`: newly constructed model
+- `field_name (str)`: name of the ormar field
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+#### add\_property\_fields
+
+```python
+add_property_fields(new_model: Type["Model"], attrs: Dict) -> None
+```
+
+Checks class namespace for properties or functions with __property_field__.
+If attribute have __property_field__ it was decorated with @property_field.
+
+Functions like this are exposed in dict() (therefore also fastapi result).
+Names of property fields are cached for quicker access / extraction.
+
+**Arguments**:
+
+- `new_model (Model class)`: newly constructed model
+- `attrs (Dict[str, str])`:
+
+
+#### register\_signals
+
+```python
+register_signals(new_model: Type["Model"]) -> None
+```
+
+Registers on model's SignalEmmiter and sets pre defined signals.
+Predefined signals are (pre/post) + (save/update/delete).
+
+Signals are emitted in both model own methods and in selected queryset ones.
+
+**Arguments**:
+
+- `new_model (Model class)`: newly constructed model
+
+
+#### update\_attrs\_and\_fields
+
+```python
+update_attrs_and_fields(attrs: Dict, new_attrs: Dict, model_fields: Dict, new_model_fields: Dict, new_fields: Set) -> Dict
+```
+
+Updates __annotations__, values of model fields (so pydantic FieldInfos)
+as well as model.Meta.model_fields definitions from parents.
+
+**Arguments**:
+
+- `attrs (Dict)`: new namespace for class being constructed
+- `new_attrs (Dict)`: part of the namespace extracted from parent class
+- `model_fields (Dict[str, BaseField])`: ormar fields in defined in current class
+- `new_model_fields (Dict[str, BaseField])`: ormar fields defined in parent classes
+- `new_fields (Set[str])`: set of new fields names
+
+
+#### verify\_constraint\_names
+
+```python
+verify_constraint_names(base_class: "Model", model_fields: Dict, parent_value: List) -> None
+```
+
+Verifies if redefined fields that are overwritten in subclasses did not remove
+any name of the column that is used in constraint as it will fail in sqlalchemy
+Table creation.
+
+**Arguments**:
+
+- `base_class (Model or model parent class)`: one of the parent classes
+- `model_fields (Dict[str, BaseField])`: ormar fields in defined in current class
+- `parent_value (List)`: list of base class constraints
+
+
+#### update\_attrs\_from\_base\_meta
+
+```python
+update_attrs_from_base_meta(base_class: "Model", attrs: Dict, model_fields: Dict) -> None
+```
+
+Updates Meta parameters in child from parent if needed.
+
+**Arguments**:
+
+- `base_class (Model or model parent class)`: one of the parent classes
+- `attrs (Dict)`: new namespace for class being constructed
+- `model_fields (Dict[str, BaseField])`: ormar fields in defined in current class
+
+
+#### copy\_data\_from\_parent\_model
+
+```python
+copy_data_from_parent_model(base_class: Type["Model"], curr_class: type, attrs: Dict, model_fields: Dict[
+ str, Union[Type[BaseField], Type[ForeignKeyField], Type[ManyToManyField]]
+ ]) -> Tuple[Dict, Dict]
+```
+
+Copy the key parameters [databse, metadata, property_fields and constraints]
+and fields from parent models. Overwrites them if needed.
+
+Only abstract classes can be subclassed.
+
+Since relation fields requires different related_name for different children
+
+
+**Raises**:
+
+- `ModelDefinitionError`: if non abstract model is subclassed
+
+**Arguments**:
+
+- `base_class (Model or model parent class)`: one of the parent classes
+- `curr_class (Model or model parent class)`: current constructed class
+- `attrs (Dict)`: new namespace for class being constructed
+- `model_fields (Dict[str, BaseField])`: ormar fields in defined in current class
+
+**Returns**:
+
+`(Tuple[Dict, Dict])`: updated attrs and model_fields
+
+
+#### extract\_from\_parents\_definition
+
+```python
+extract_from_parents_definition(base_class: type, curr_class: type, attrs: Dict, model_fields: Dict[
+ str, Union[Type[BaseField], Type[ForeignKeyField], Type[ManyToManyField]]
+ ]) -> Tuple[Dict, Dict]
+```
+
+Extracts fields from base classes if they have valid oramr fields.
+
+If model was already parsed -> fields definitions need to be removed from class
+cause pydantic complains about field re-definition so after first child
+we need to extract from __parsed_fields__ not the class itself.
+
+If the class is parsed first time annotations and field definition is parsed
+from the class.__dict__.
+
+If the class is a ormar.Model it is skipped.
+
+**Arguments**:
+
+- `base_class (Model or model parent class)`: one of the parent classes
+- `curr_class (Model or model parent class)`: current constructed class
+- `attrs (Dict)`: new namespace for class being constructed
+- `model_fields (Dict[str, BaseField])`: ormar fields in defined in current class
+
+**Returns**:
+
+`(Tuple[Dict, Dict])`: updated attrs and model_fields
+
+
+## ModelMetaclass Objects
+
+```python
+class ModelMetaclass(pydantic.main.ModelMetaclass)
+```
+
+
+#### \_\_new\_\_
+
+```python
+ | __new__(mcs: "ModelMetaclass", name: str, bases: Any, attrs: dict) -> "ModelMetaclass"
+```
+
+Metaclass used by ormar Models that performs configuration
+and build of ormar Models.
+
+
+Sets pydantic configuration.
+Extract model_fields and convert them to pydantic FieldInfo,
+updates class namespace.
+
+Extracts settings and fields from parent classes.
+Fetches methods decorated with @property_field decorator
+to expose them later in dict().
+
+Construct parent pydantic Metaclass/ Model.
+
+If class has Meta class declared (so actual ormar Models) it also:
+
+* populate sqlalchemy columns, pkname and tables from model_fields
+* register reverse relationships on related models
+* registers all relations in alias manager that populates table_prefixes
+* exposes alias manager on each Model
+* creates QuerySet for each model and exposes it on a class
+
+**Arguments**:
+
+- `name (str)`: name of current class
+- `bases (Tuple)`: base classes
+- `attrs (Dict)`: class namespace
+
diff --git a/docs/api/models/model-table-proxy.md b/docs/api/models/model-table-proxy.md
new file mode 100644
index 0000000..eb79f52
--- /dev/null
+++ b/docs/api/models/model-table-proxy.md
@@ -0,0 +1,14 @@
+
+# models.modelproxy
+
+
+## ModelTableProxy Objects
+
+```python
+class ModelTableProxy(
+ PrefetchQueryMixin, MergeModelMixin, SavePrepareMixin, ExcludableMixin)
+```
+
+Used to combine all mixins with different set of functionalities.
+One of the bases of the ormar Model class.
+
diff --git a/docs/api/models/model.md b/docs/api/models/model.md
new file mode 100644
index 0000000..b22d3d9
--- /dev/null
+++ b/docs/api/models/model.md
@@ -0,0 +1,323 @@
+
+# models.model
+
+
+#### group\_related\_list
+
+```python
+group_related_list(list_: List) -> Dict
+```
+
+Translates the list of related strings into a dictionary.
+That way nested models are grouped to traverse them in a right order
+and to avoid repetition.
+
+Sample: ["people__houses", "people__cars__models", "people__cars__colors"]
+will become:
+{'people': {'houses': [], 'cars': ['models', 'colors']}}
+
+**Arguments**:
+
+- `list_ (List[str])`: list of related models used in select related
+
+**Returns**:
+
+`(Dict[str, List])`: list converted to dictionary to avoid repetition and group nested models
+
+
+#### T
+
+
+## Model Objects
+
+```python
+class Model(NewBaseModel)
+```
+
+
+#### \_\_abstract\_\_
+
+
+#### \_\_repr\_\_
+
+```python
+ | __repr__() -> str
+```
+
+
+#### from\_row
+
+```python
+ | @classmethod
+ | from_row(cls: Type[T], row: sqlalchemy.engine.ResultProxy, select_related: List = None, related_models: Any = None, previous_model: Type[T] = None, related_name: str = None, fields: Optional[Union[Dict, Set]] = None, exclude_fields: Optional[Union[Dict, Set]] = None) -> Optional[T]
+```
+
+Model method to convert raw sql row from database into ormar.Model instance.
+Traverses nested models if they were specified in select_related for query.
+
+Called recurrently and returns model instance if it's present in the row.
+Note that it's processing one row at a time, so if there are duplicates of
+parent row that needs to be joined/combined
+(like parent row in sql join with 2+ child rows)
+instances populated in this method are later combined in the QuerySet.
+Other method working directly on raw database results is in prefetch_query,
+where rows are populated in a different way as they do not have
+nested models in result.
+
+**Arguments**:
+
+- `row (sqlalchemy.engine.result.ResultProxy)`: raw result row from the database
+- `select_related (List)`: list of names of related models fetched from database
+- `related_models (Union[List, Dict])`: list or dict of related models
+- `previous_model (Model class)`: internal param for nested models to specify table_prefix
+- `related_name (str)`: internal parameter - name of current nested model
+- `fields (Optional[Union[Dict, Set]])`: fields and related model fields to include
+if provided only those are included
+- `exclude_fields (Optional[Union[Dict, Set]])`: fields and related model fields to exclude
+excludes the fields even if they are provided in fields
+
+**Returns**:
+
+`(Optional[Model])`: returns model if model is populated from database
+
+
+#### populate\_nested\_models\_from\_row
+
+```python
+ | @classmethod
+ | populate_nested_models_from_row(cls, item: dict, row: sqlalchemy.engine.ResultProxy, related_models: Any, fields: Optional[Union[Dict, Set]] = None, exclude_fields: Optional[Union[Dict, Set]] = None) -> dict
+```
+
+Traverses structure of related models and populates the nested models
+from the database row.
+Related models can be a list if only directly related models are to be
+populated, converted to dict if related models also have their own related
+models to be populated.
+
+Recurrently calls from_row method on nested instances and create nested
+instances. In the end those instances are added to the final model dictionary.
+
+**Arguments**:
+
+- `item (Dict)`: dictionary of already populated nested models, otherwise empty dict
+- `row (sqlalchemy.engine.result.ResultProxy)`: raw result row from the database
+- `related_models (Union[Dict, List])`: list or dict of related models
+- `fields (Optional[Union[Dict, Set]])`: fields and related model fields to include -
+if provided only those are included
+- `exclude_fields (Optional[Union[Dict, Set]])`: fields and related model fields to exclude
+excludes the fields even if they are provided in fields
+
+**Returns**:
+
+`(Dict)`: dictionary with keys corresponding to model fields names
+and values are database values
+
+
+#### extract\_prefixed\_table\_columns
+
+```python
+ | @classmethod
+ | extract_prefixed_table_columns(cls, item: dict, row: sqlalchemy.engine.result.ResultProxy, table_prefix: str, fields: Optional[Union[Dict, Set]] = None, exclude_fields: Optional[Union[Dict, Set]] = None) -> dict
+```
+
+Extracts own fields from raw sql result, using a given prefix.
+Prefix changes depending on the table's position in a join.
+
+If the table is a main table, there is no prefix.
+All joined tables have prefixes to allow duplicate column names,
+as well as duplicated joins to the same table from multiple different tables.
+
+Extracted fields populates the item dict later used to construct a Model.
+
+Used in Model.from_row and PrefetchQuery._populate_rows methods.
+
+**Arguments**:
+
+- `item (Dict)`: dictionary of already populated nested models, otherwise empty dict
+- `row (sqlalchemy.engine.result.ResultProxy)`: raw result row from the database
+- `table_prefix (str)`: prefix of the table from AliasManager
+each pair of tables have own prefix (two of them depending on direction) -
+used in joins to allow multiple joins to the same table.
+- `fields (Optional[Union[Dict, Set]])`: fields and related model fields to include -
+if provided only those are included
+- `exclude_fields (Optional[Union[Dict, Set]])`: fields and related model fields to exclude
+excludes the fields even if they are provided in fields
+
+**Returns**:
+
+`(Dict)`: dictionary with keys corresponding to model fields names
+and values are database values
+
+
+#### upsert
+
+```python
+ | async upsert(**kwargs: Any) -> T
+```
+
+Performs either a save or an update depending on the presence of the pk.
+If the pk field is filled it's an update, otherwise the save is performed.
+For save kwargs are ignored, used only in update if provided.
+
+**Arguments**:
+
+- `kwargs (Any)`: list of fields to update
+
+**Returns**:
+
+`(Model)`: saved Model
+
+
+#### save
+
+```python
+ | async save() -> T
+```
+
+Performs a save of given Model instance.
+If primary key is already saved, db backend will throw integrity error.
+
+Related models are saved by pk number, reverse relation and many to many fields
+are not saved - use corresponding relations methods.
+
+If there are fields with server_default set and those fields
+are not already filled save will trigger also a second query
+to refreshed the fields populated server side.
+
+Does not recognize if model was previously saved.
+If you want to perform update or insert depending on the pk
+fields presence use upsert.
+
+Sends pre_save and post_save signals.
+
+Sets model save status to True.
+
+**Returns**:
+
+`(Model)`: saved Model
+
+
+#### save\_related
+
+```python
+ | async save_related(follow: bool = False, visited: Set = None, update_count: int = 0) -> int
+```
+
+Triggers a upsert method on all related models
+if the instances are not already saved.
+By default saves only the directly related ones.
+
+If follow=True is set it saves also related models of related models.
+
+To not get stuck in an infinite loop as related models also keep a relation
+to parent model visited models set is kept.
+
+That way already visited models that are nested are saved, but the save do not
+follow them inside. So Model A -> Model B -> Model A -> Model C will save second
+Model A but will never follow into Model C.
+Nested relations of those kind need to be persisted manually.
+
+**Arguments**:
+
+- `follow (bool)`: flag to trigger deep save -
+by default only directly related models are saved
+with follow=True also related models of related models are saved
+- `visited (Set)`: internal parameter for recursive calls - already visited models
+- `update_count (int)`: internal parameter for recursive calls -
+number of updated instances
+
+**Returns**:
+
+`(int)`: number of updated/saved models
+
+
+#### \_update\_and\_follow
+
+```python
+ | @staticmethod
+ | async _update_and_follow(rel: T, follow: bool, visited: Set, update_count: int) -> Tuple[int, Set]
+```
+
+Internal method used in save_related to follow related models and update numbers
+of updated related instances.
+
+**Arguments**:
+
+- `rel (Model)`: Model to follow
+- `follow (bool)`: flag to trigger deep save -
+by default only directly related models are saved
+with follow=True also related models of related models are saved
+- `visited (Set)`: internal parameter for recursive calls - already visited models
+- `update_count (int)`: internal parameter for recursive calls -
+number of updated instances
+
+**Returns**:
+
+`(Tuple[int, Set])`: tuple of update count and visited
+
+
+#### update
+
+```python
+ | async update(**kwargs: Any) -> T
+```
+
+Performs update of Model instance in the database.
+Fields can be updated before or you can pass them as kwargs.
+
+Sends pre_update and post_update signals.
+
+Sets model save status to True.
+
+**Raises**:
+
+- `ModelPersistenceError`: If the pk column is not set will throw ModelPersistenceError
+
+**Arguments**:
+
+- `kwargs (Any)`: list of fields to update as field=value pairs
+
+**Returns**:
+
+`(Model)`: updated Model
+
+
+#### delete
+
+```python
+ | async delete() -> int
+```
+
+Removes the Model instance from the database.
+
+Sends pre_delete and post_delete signals.
+
+Sets model save status to False.
+
+Note it does not delete the Model itself (python object).
+So you can delete and later save (since pk is deleted no conflict will arise)
+or update and the Model will be saved in database again.
+
+**Returns**:
+
+`(int)`: number of deleted rows (for some backends)
+
+
+#### load
+
+```python
+ | async load() -> T
+```
+
+Allow to refresh existing Models fields from database.
+Be careful as the related models can be overwritten by pk_only models in load.
+Does NOT refresh the related models fields if they were loaded before.
+
+**Raises**:
+
+- `NoMatch`: If given pk is not found in database the NoMatch exception is raised.
+
+**Returns**:
+
+`(Model)`: reloaded Model
+
diff --git a/docs/api/models/new-basemodel.md b/docs/api/models/new-basemodel.md
new file mode 100644
index 0000000..0190131
--- /dev/null
+++ b/docs/api/models/new-basemodel.md
@@ -0,0 +1,512 @@
+
+# models.newbasemodel
+
+
+## NewBaseModel Objects
+
+```python
+class NewBaseModel(pydantic.BaseModel, ModelTableProxy, metaclass=ModelMetaclass)
+```
+
+Main base class of ormar Model.
+Inherits from pydantic BaseModel and has all mixins combined in ModelTableProxy.
+Constructed with ModelMetaclass which in turn also inherits pydantic metaclass.
+
+Abstracts away all internals and helper functions, so final Model class has only
+the logic concerned with database connection and data persistance.
+
+
+#### \_\_slots\_\_
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(*args: Any, **kwargs: Any) -> None
+```
+
+Initializer that creates a new ormar Model that is also pydantic Model at the
+same time.
+
+Passed keyword arguments can be only field names and their corresponding values
+as those will be passed to pydantic validation that will complain if extra
+params are passed.
+
+If relations are defined each relation is expanded and children models are also
+initialized and validated. Relation from both sides is registered so you can
+access related models from both sides.
+
+Json fields are automatically loaded/dumped if needed.
+
+Models marked as abstract=True in internal Meta class cannot be initialized.
+
+Accepts also special __pk_only__ flag that indicates that Model is constructed
+only with primary key value (so no other fields, it's a child model on other
+Model), that causes skipping the validation, that's the only case when the
+validation can be skipped.
+
+Accepts also special __excluded__ parameter that contains a set of fields that
+should be explicitly set to None, as otherwise pydantic will try to populate
+them with their default values if default is set.
+
+**Raises**:
+
+- `ModelError`: if abstract model is initialized or unknown field is passed
+
+**Arguments**:
+
+- `args (Any)`: ignored args
+- `kwargs (Any)`: keyword arguments - all fields values and some special params
+
+
+#### \_\_setattr\_\_
+
+```python
+ | __setattr__(name: str, value: Any) -> None
+```
+
+Overwrites setattr in object to allow for special behaviour of certain params.
+
+Parameter "pk" is translated into actual primary key field name.
+
+Relations are expanded (child model constructed if needed) and registered on
+both ends of the relation. The related models are handled by RelationshipManager
+exposed at _orm param.
+
+Json fields converted if needed.
+
+Setting pk, foreign key value or any other field value sets Model save status
+to False. Setting a reverse relation or many to many relation does not as it
+does not modify the state of the model (but related model or through model).
+
+To short circuit all checks and expansions the set of attribute names present
+on each model is gathered into _quick_access_fields that is looked first and
+if field is in this set the object setattr is called directly.
+
+**Arguments**:
+
+- `name (str)`: name of the attribute to set
+- `value (Any)`: value of the attribute to set
+
+**Returns**:
+
+`(None)`: None
+
+
+#### \_\_getattribute\_\_
+
+```python
+ | __getattribute__(item: str) -> Any
+```
+
+Because we need to overwrite getting the attribute by ormar instead of pydantic
+as well as returning related models and not the value stored on the model the
+__getattribute__ needs to be used not __getattr__.
+
+It's used to access all attributes so it can be a big overhead that's why a
+number of short circuits is used.
+
+To short circuit all checks and expansions the set of attribute names present
+on each model is gathered into _quick_access_fields that is looked first and
+if field is in this set the object setattr is called directly.
+
+To avoid recursion object's getattribute is used to actually get the attribute
+value from the model after the checks.
+
+Even the function calls are constructed with objects functions.
+
+Parameter "pk" is translated into actual primary key field name.
+
+Relations are returned so the actual related model is returned and not current
+model's field. The related models are handled by RelationshipManager exposed
+at _orm param.
+
+Json fields are converted if needed.
+
+**Arguments**:
+
+- `item (str)`: name of the attribute to retrieve
+
+**Returns**:
+
+`(Any)`: value of the attribute
+
+
+#### \_extract\_related\_model\_instead\_of\_field
+
+```python
+ | _extract_related_model_instead_of_field(item: str) -> Optional[Union["T", Sequence["T"]]]
+```
+
+Retrieves the related model/models from RelationshipManager.
+
+**Arguments**:
+
+- `item (str)`: name of the relation
+
+**Returns**:
+
+`(Optional[Union[Model, List[Model]]])`: related model, list of related models or None
+
+
+#### \_\_eq\_\_
+
+```python
+ | __eq__(other: object) -> bool
+```
+
+Compares other model to this model. when == is called.
+
+**Arguments**:
+
+- `other (object)`: other model to compare
+
+**Returns**:
+
+`(bool)`: result of comparison
+
+
+#### \_\_same\_\_
+
+```python
+ | __same__(other: "NewBaseModel") -> bool
+```
+
+Used by __eq__, compares other model to this model.
+Compares:
+* _orm_ids,
+* primary key values if it's set
+* dictionary of own fields (excluding relations)
+
+**Arguments**:
+
+- `other (NewBaseModel)`: model to compare to
+
+**Returns**:
+
+`(bool)`: result of comparison
+
+
+#### get\_name
+
+```python
+ | @classmethod
+ | get_name(cls, lower: bool = True) -> str
+```
+
+Returns name of the Model class, by default lowercase.
+
+**Arguments**:
+
+- `lower (bool)`: flag if name should be set to lowercase
+
+**Returns**:
+
+`(str)`: name of the model
+
+
+#### pk\_column
+
+```python
+ | @property
+ | pk_column() -> sqlalchemy.Column
+```
+
+Retrieves primary key sqlalchemy column from models Meta.table.
+Each model has to have primary key.
+Only one primary key column is allowed.
+
+**Returns**:
+
+`(sqlalchemy.Column)`: primary key sqlalchemy column
+
+
+#### saved
+
+```python
+ | @property
+ | saved() -> bool
+```
+
+Saved status of the model. Changed by setattr and loading from db
+
+
+#### signals
+
+```python
+ | @property
+ | signals() -> "SignalEmitter"
+```
+
+Exposes signals from model Meta
+
+
+#### pk\_type
+
+```python
+ | @classmethod
+ | pk_type(cls) -> Any
+```
+
+Shortcut to models primary key field type
+
+
+#### db\_backend\_name
+
+```python
+ | @classmethod
+ | db_backend_name(cls) -> str
+```
+
+Shortcut to database dialect,
+cause some dialect require different treatment
+
+
+#### remove
+
+```python
+ | remove(parent: "T", name: str) -> None
+```
+
+Removes child from relation with given name in RelationshipManager
+
+
+#### set\_save\_status
+
+```python
+ | set_save_status(status: bool) -> None
+```
+
+Sets value of the save status
+
+
+#### get\_properties
+
+```python
+ | @classmethod
+ | get_properties(cls, include: Union[Set, Dict, None], exclude: Union[Set, Dict, None]) -> Set[str]
+```
+
+Returns a set of names of functions/fields decorated with
+@property_field decorator.
+
+They are added to dictionary when called directly and therefore also are
+present in fastapi responses.
+
+**Arguments**:
+
+- `include (Union[Set, Dict, None])`: fields to include
+- `exclude (Union[Set, Dict, None])`: fields to exclude
+
+**Returns**:
+
+`(Set[str])`: set of property fields names
+
+
+#### \_get\_related\_not\_excluded\_fields
+
+```python
+ | _get_related_not_excluded_fields(include: Optional[Dict], exclude: Optional[Dict]) -> List
+```
+
+Returns related field names applying on them include and exclude set.
+
+**Arguments**:
+
+- `include (Union[Set, Dict, None])`: fields to include
+- `exclude (Union[Set, Dict, None])`: fields to exclude
+
+**Returns**:
+
+`(List of fields with relations that is not excluded)`:
+
+
+#### \_extract\_nested\_models\_from\_list
+
+```python
+ | @staticmethod
+ | _extract_nested_models_from_list(models: MutableSequence, include: Union[Set, Dict, None], exclude: Union[Set, Dict, None]) -> List
+```
+
+Converts list of models into list of dictionaries.
+
+**Arguments**:
+
+- `models (List)`: List of models
+- `include (Union[Set, Dict, None])`: fields to include
+- `exclude (Union[Set, Dict, None])`: fields to exclude
+
+**Returns**:
+
+`(List[Dict])`: list of models converted to dictionaries
+
+
+#### \_skip\_ellipsis
+
+```python
+ | _skip_ellipsis(items: Union[Set, Dict, None], key: str) -> Union[Set, Dict, None]
+```
+
+Helper to traverse the include/exclude dictionaries.
+In dict() Ellipsis should be skipped as it indicates all fields required
+and not the actual set/dict with fields names.
+
+**Arguments**:
+
+- `items (Union[Set, Dict, None])`: current include/exclude value
+- `key (str)`: key for nested relations to check
+
+**Returns**:
+
+`(Union[Set, Dict, None])`: nested value of the items
+
+
+#### \_extract\_nested\_models
+
+```python
+ | _extract_nested_models(nested: bool, dict_instance: Dict, include: Optional[Dict], exclude: Optional[Dict]) -> Dict
+```
+
+Traverse nested models and converts them into dictionaries.
+Calls itself recursively if needed.
+
+**Arguments**:
+
+- `nested (bool)`: flag if current instance is nested
+- `dict_instance (Dict)`: current instance dict
+- `include (Optional[Dict])`: fields to include
+- `exclude (Optional[Dict])`: fields to exclude
+
+**Returns**:
+
+`(Dict)`: current model dict with child models converted to dictionaries
+
+
+#### dict
+
+```python
+ | dict(*, include: Union[Set, Dict] = None, exclude: Union[Set, Dict] = None, by_alias: bool = False, skip_defaults: bool = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, nested: bool = False) -> "DictStrAny"
+```
+
+Generate a dictionary representation of the model,
+optionally specifying which fields to include or exclude.
+
+Nested models are also parsed to dictionaries.
+
+Additionally fields decorated with @property_field are also added.
+
+**Arguments**:
+
+- `include (Union[Set, Dict, None])`: fields to include
+- `exclude (Union[Set, Dict, None])`: fields to exclude
+- `by_alias (bool)`: flag to get values by alias - passed to pydantic
+- `skip_defaults (bool)`: flag to not set values - passed to pydantic
+- `exclude_unset (bool)`: flag to exclude not set values - passed to pydantic
+- `exclude_defaults (bool)`: flag to exclude default values - passed to pydantic
+- `exclude_none (bool)`: flag to exclude None values - passed to pydantic
+- `nested (bool)`: flag if the current model is nested
+
+**Returns**:
+
+`()`:
+
+
+#### update\_from\_dict
+
+```python
+ | update_from_dict(value_dict: Dict) -> "NewBaseModel"
+```
+
+Updates self with values of fields passed in the dictionary.
+
+**Arguments**:
+
+- `value_dict (Dict)`: dictionary of fields names and values
+
+**Returns**:
+
+`(NewBaseModel)`: self
+
+
+#### \_convert\_json
+
+```python
+ | _convert_json(column_name: str, value: Any, op: str) -> Union[str, Dict]
+```
+
+Converts value to/from json if needed (for Json columns).
+
+**Arguments**:
+
+- `column_name (str)`: name of the field
+- `value (Any)`: value fo the field
+- `op (str)`: operator on json
+
+**Returns**:
+
+`(Any)`: converted value if needed, else original value
+
+
+#### \_is\_conversion\_to\_json\_needed
+
+```python
+ | _is_conversion_to_json_needed(column_name: str) -> bool
+```
+
+Checks if given column name is related to JSON field.
+
+**Arguments**:
+
+- `column_name (str)`: name of the field
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+#### \_extract\_own\_model\_fields
+
+```python
+ | _extract_own_model_fields() -> Dict
+```
+
+Returns a dictionary with field names and values for fields that are not
+relations fields (ForeignKey, ManyToMany etc.)
+
+**Returns**:
+
+`(Dict)`: dictionary of fields names and values.
+
+
+#### \_extract\_model\_db\_fields
+
+```python
+ | _extract_model_db_fields() -> Dict
+```
+
+Returns a dictionary with field names and values for fields that are stored in
+current model's table.
+
+That includes own non-relational fields ang foreign key fields.
+
+**Returns**:
+
+`(Dict)`: dictionary of fields names and values.
+
+
+#### get\_relation\_model\_id
+
+```python
+ | get_relation_model_id(target_field: Type["BaseField"]) -> Optional[int]
+```
+
+Returns an id of the relation side model to use in prefetch query.
+
+**Arguments**:
+
+- `target_field (Type["BaseField"])`: field with relation definition
+
+**Returns**:
+
+`(Optional[int])`: value of pk if set
+
diff --git a/docs/api/query-set/clause.md b/docs/api/query-set/clause.md
new file mode 100644
index 0000000..dcef64d
--- /dev/null
+++ b/docs/api/query-set/clause.md
@@ -0,0 +1,174 @@
+
+# queryset.clause
+
+
+#### FILTER\_OPERATORS
+
+
+#### ESCAPE\_CHARACTERS
+
+
+## QueryClause Objects
+
+```python
+class QueryClause()
+```
+
+Constructs where clauses from strings passed as arguments
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(model_cls: Type["Model"], filter_clauses: List, select_related: List) -> None
+```
+
+
+#### filter
+
+```python
+ | filter(**kwargs: Any) -> Tuple[List[sqlalchemy.sql.expression.TextClause], List[str]]
+```
+
+Main external access point that processes the clauses into sqlalchemy text
+clauses and updates select_related list with implicit related tables
+mentioned in select_related strings but not included in select_related.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pair with column names and values
+
+**Returns**:
+
+`(Tuple[List[sqlalchemy.sql.elements.TextClause], List[str]])`: Tuple with list of where clauses and updated select_related list
+
+
+#### \_populate\_filter\_clauses
+
+```python
+ | _populate_filter_clauses(**kwargs: Any) -> Tuple[List[sqlalchemy.sql.expression.TextClause], List[str]]
+```
+
+Iterates all clauses and extracts used operator and field from related
+models if needed. Based on the chain of related names the target table
+is determined and the final clause is escaped if needed and compiled.
+
+**Arguments**:
+
+- `kwargs (Any)`: key, value pair with column names and values
+
+**Returns**:
+
+`(Tuple[List[sqlalchemy.sql.elements.TextClause], List[str]])`: Tuple with list of where clauses and updated select_related list
+
+
+#### \_process\_column\_clause\_for\_operator\_and\_value
+
+```python
+ | _process_column_clause_for_operator_and_value(value: Any, op: str, column: sqlalchemy.Column, table: sqlalchemy.Table, table_prefix: str) -> sqlalchemy.sql.expression.TextClause
+```
+
+Escapes characters if it's required.
+Substitutes values of the models if value is a ormar Model with its pk value.
+Compiles the clause.
+
+**Arguments**:
+
+- `value (Any)`: value of the filter
+- `op (str)`: filter operator
+- `column (sqlalchemy.sql.schema.Column)`: column on which filter should be applied
+- `table (sqlalchemy.sql.schema.Table)`: table on which filter should be applied
+- `table_prefix (str)`: prefix from AliasManager
+
+**Returns**:
+
+`(sqlalchemy.sql.elements.TextClause)`: complied and escaped clause
+
+
+#### \_determine\_filter\_target\_table
+
+```python
+ | _determine_filter_target_table(related_parts: List[str], select_related: List[str]) -> Tuple[List[str], str, Type["Model"]]
+```
+
+Adds related strings to select_related list otherwise the clause would fail as
+the required columns would not be present. That means that select_related
+list is filled with missing values present in filters.
+
+Walks the relation to retrieve the actual model on which the clause should be
+constructed, extracts alias based on last relation leading to target model.
+
+**Arguments**:
+
+- `related_parts (List[str])`: list of split parts of related string
+- `select_related (List[str])`: list of related models
+
+**Returns**:
+
+`(Tuple[List[str], str, Type[Model]])`: list of related models, table_prefix, final model class
+
+
+#### \_compile\_clause
+
+```python
+ | _compile_clause(clause: sqlalchemy.sql.expression.BinaryExpression, column: sqlalchemy.Column, table: sqlalchemy.Table, table_prefix: str, modifiers: Dict) -> sqlalchemy.sql.expression.TextClause
+```
+
+Compiles the clause to str using appropriate database dialect, replace columns
+names with aliased names and converts it back to TextClause.
+
+**Arguments**:
+
+- `clause (sqlalchemy.sql.elements.BinaryExpression)`: original not compiled clause
+- `column (sqlalchemy.sql.schema.Column)`: column on which filter should be applied
+- `table (sqlalchemy.sql.schema.Table)`: table on which filter should be applied
+- `table_prefix (str)`: prefix from AliasManager
+- `modifiers (Dict[str, NoneType])`: sqlalchemy modifiers - used only to escape chars here
+
+**Returns**:
+
+`(sqlalchemy.sql.elements.TextClause)`: compiled and escaped clause
+
+
+#### \_escape\_characters\_in\_clause
+
+```python
+ | @staticmethod
+ | _escape_characters_in_clause(op: str, value: Any) -> Tuple[Any, bool]
+```
+
+Escapes the special characters ["%", "_"] if needed.
+Adds `%` for `like` queries.
+
+**Raises**:
+
+- `QueryDefinitionError`: if contains or icontains is used with
+ormar model instance
+
+**Arguments**:
+
+- `op (str)`: operator used in query
+- `value (Any)`: value of the filter
+
+**Returns**:
+
+`(Tuple[Any, bool])`: escaped value and flag if escaping is needed
+
+
+#### \_extract\_operator\_field\_and\_related
+
+```python
+ | @staticmethod
+ | _extract_operator_field_and_related(parts: List[str]) -> Tuple[str, str, Optional[List]]
+```
+
+Splits filter query key and extracts required parts.
+
+**Arguments**:
+
+- `parts (List[str])`: split filter query key
+
+**Returns**:
+
+`(Tuple[str, str, Optional[List]])`: operator, field_name, list of related parts
+
diff --git a/docs/api/query-set/filter-query.md b/docs/api/query-set/filter-query.md
new file mode 100644
index 0000000..5a3b68e
--- /dev/null
+++ b/docs/api/query-set/filter-query.md
@@ -0,0 +1,36 @@
+
+# queryset.filter\_query
+
+
+## FilterQuery Objects
+
+```python
+class FilterQuery()
+```
+
+Modifies the select query with given list of where/filter clauses.
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(filter_clauses: List, exclude: bool = False) -> None
+```
+
+
+#### apply
+
+```python
+ | apply(expr: sqlalchemy.sql.select) -> sqlalchemy.sql.select
+```
+
+Applies all filter clauses if set.
+
+**Arguments**:
+
+- `expr (sqlalchemy.sql.selectable.Select)`: query to modify
+
+**Returns**:
+
+`(sqlalchemy.sql.selectable.Select)`: modified query
+
diff --git a/docs/api/query-set/join.md b/docs/api/query-set/join.md
new file mode 100644
index 0000000..8519c54
--- /dev/null
+++ b/docs/api/query-set/join.md
@@ -0,0 +1,262 @@
+
+# queryset.join
+
+
+## JoinParameters Objects
+
+```python
+class JoinParameters(NamedTuple)
+```
+
+Named tuple that holds set of parameters passed during join construction.
+
+
+#### prev\_model
+
+
+#### previous\_alias
+
+
+#### from\_table
+
+
+#### model\_cls
+
+
+## SqlJoin Objects
+
+```python
+class SqlJoin()
+```
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(used_aliases: List, select_from: sqlalchemy.sql.select, columns: List[sqlalchemy.Column], fields: Optional[Union[Set, Dict]], exclude_fields: Optional[Union[Set, Dict]], order_columns: Optional[List], sorted_orders: OrderedDict) -> None
+```
+
+
+#### alias\_manager
+
+```python
+ | @staticmethod
+ | alias_manager(model_cls: Type["Model"]) -> AliasManager
+```
+
+Shortcut for ormars model AliasManager stored on Meta.
+
+**Arguments**:
+
+- `model_cls (Type[Model])`: ormar Model class
+
+**Returns**:
+
+`(AliasManager)`: alias manager from model's Meta
+
+
+#### on\_clause
+
+```python
+ | @staticmethod
+ | on_clause(previous_alias: str, alias: str, from_clause: str, to_clause: str) -> text
+```
+
+Receives aliases and names of both ends of the join and combines them
+into one text clause used in joins.
+
+**Arguments**:
+
+- `previous_alias (str)`: alias of previous table
+- `alias (str)`: alias of current table
+- `from_clause (str)`: from table name
+- `to_clause (str)`: to table name
+
+**Returns**:
+
+`(sqlalchemy.text)`: clause combining all strings
+
+
+#### update\_inclusions
+
+```python
+ | @staticmethod
+ | update_inclusions(model_cls: Type["Model"], fields: Optional[Union[Set, Dict]], exclude_fields: Optional[Union[Set, Dict]], nested_name: str) -> Tuple[Optional[Union[Dict, Set]], Optional[Union[Dict, Set]]]
+```
+
+Extract nested fields and exclude_fields if applicable.
+
+**Arguments**:
+
+- `model_cls (Type["Model"])`: ormar model class
+- `fields (Optional[Union[Set, Dict]])`: fields to include
+- `exclude_fields (Optional[Union[Set, Dict]])`: fields to exclude
+- `nested_name (str)`: name of the nested field
+
+**Returns**:
+
+`(Tuple[Optional[Union[Dict, Set]], Optional[Union[Dict, Set]]])`: updated exclude and include fields from nested objects
+
+
+#### build\_join
+
+```python
+ | build_join(item: str, join_parameters: JoinParameters) -> Tuple[List, sqlalchemy.sql.select, List, OrderedDict]
+```
+
+Main external access point for building a join.
+Splits the join definition, updates fields and exclude_fields if needed,
+handles switching to through models for m2m relations, returns updated lists of
+used_aliases and sort_orders.
+
+**Arguments**:
+
+- `item (str)`: string with join definition
+- `join_parameters (JoinParameters)`: parameters from previous/ current join
+
+**Returns**:
+
+`(Tuple[List[str], Join, List[TextClause], collections.OrderedDict])`: list of used aliases, select from, list of aliased columns, sort orders
+
+
+#### \_build\_join\_parameters
+
+```python
+ | _build_join_parameters(part: str, join_params: JoinParameters, fields: Optional[Union[Set, Dict]], exclude_fields: Optional[Union[Set, Dict]], is_multi: bool = False) -> JoinParameters
+```
+
+Updates used_aliases to not join multiple times to the same table.
+Updates join parameters with new values.
+
+**Arguments**:
+
+- `part (str)`: part of the join str definition
+- `join_params (JoinParameters)`: parameters from previous/ current join
+- `fields (Optional[Union[Set, Dict]])`: fields to include
+- `exclude_fields (Optional[Union[Set, Dict]])`: fields to exclude
+- `is_multi (bool)`: flag if the relation is m2m
+
+**Returns**:
+
+`(ormar.queryset.join.JoinParameters)`: updated join parameters
+
+
+#### \_process\_join
+
+```python
+ | _process_join(join_params: JoinParameters, is_multi: bool, model_cls: Type["Model"], part: str, alias: str, fields: Optional[Union[Set, Dict]], exclude_fields: Optional[Union[Set, Dict]]) -> None
+```
+
+Resolves to and from column names and table names.
+
+Produces on_clause.
+
+Performs actual join updating select_from parameter.
+
+Adds aliases of required column to list of columns to include in query.
+
+Updates the used aliases list directly.
+
+Process order_by causes for non m2m relations.
+
+**Arguments**:
+
+- `join_params (JoinParameters)`: parameters from previous/ current join
+- `is_multi (bool)`: flag if it's m2m relation
+- `model_cls (ormar.models.metaclass.ModelMetaclass)`:
+- `part (str)`: name of the field used in join
+- `alias (str)`: alias of the current join
+- `fields (Optional[Union[Set, Dict]])`: fields to include
+- `exclude_fields (Optional[Union[Set, Dict]])`: fields to exclude
+
+
+#### \_switch\_many\_to\_many\_order\_columns
+
+```python
+ | _switch_many_to_many_order_columns(part: str, new_part: str) -> None
+```
+
+Substitutes the name of the relation with actual model name in m2m order bys.
+
+**Arguments**:
+
+- `part (str)`: name of the field with relation
+- `new_part (str)`: name of the target model
+
+
+#### \_check\_if\_condition\_apply
+
+```python
+ | @staticmethod
+ | _check_if_condition_apply(condition: List, part: str) -> bool
+```
+
+Checks filter conditions to find if they apply to current join.
+
+**Arguments**:
+
+- `condition (List[str])`: list of parts of condition split by '__'
+- `part (str)`: name of the current relation join.
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+#### set\_aliased\_order\_by
+
+```python
+ | set_aliased_order_by(condition: List[str], alias: str, to_table: str, model_cls: Type["Model"]) -> None
+```
+
+Substitute hyphens ('-') with descending order.
+Construct actual sqlalchemy text clause using aliased table and column name.
+
+**Arguments**:
+
+- `condition (List[str])`: list of parts of a current condition split by '__'
+- `alias (str)`: alias of the table in current join
+- `to_table (sqlalchemy.sql.elements.quoted_name)`: target table
+- `model_cls (ormar.models.metaclass.ModelMetaclass)`: ormar model class
+
+
+#### get\_order\_bys
+
+```python
+ | get_order_bys(alias: str, to_table: str, pkname_alias: str, part: str, model_cls: Type["Model"]) -> None
+```
+
+Triggers construction of order bys if they are given.
+Otherwise by default each table is sorted by a primary key column asc.
+
+**Arguments**:
+
+- `alias (str)`: alias of current table in join
+- `to_table (sqlalchemy.sql.elements.quoted_name)`: target table
+- `pkname_alias (str)`: alias of the primary key column
+- `part (str)`: name of the current relation join
+- `model_cls (Type[Model])`: ormar model class
+
+
+#### get\_to\_and\_from\_keys
+
+```python
+ | @staticmethod
+ | get_to_and_from_keys(join_params: JoinParameters, is_multi: bool, model_cls: Type["Model"], part: str) -> Tuple[str, str]
+```
+
+Based on the relation type, name of the relation and previous models and parts
+stored in JoinParameters it resolves the current to and from keys, which are
+different for ManyToMany relation, ForeignKey and reverse part of relations.
+
+**Arguments**:
+
+- `join_params (JoinParameters)`: parameters from previous/ current join
+- `is_multi (bool)`: flag if the relation is of m2m type
+- `model_cls (Type[Model])`: ormar model class
+- `part (str)`: name of the current relation join
+
+**Returns**:
+
+`(Tuple[str, str])`: to key and from key
+
diff --git a/docs/api/query-set/limit-query.md b/docs/api/query-set/limit-query.md
new file mode 100644
index 0000000..5e9e973
--- /dev/null
+++ b/docs/api/query-set/limit-query.md
@@ -0,0 +1,36 @@
+
+# queryset.limit\_query
+
+
+## LimitQuery Objects
+
+```python
+class LimitQuery()
+```
+
+Modifies the select query with limit clause.
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(limit_count: Optional[int]) -> None
+```
+
+
+#### apply
+
+```python
+ | apply(expr: sqlalchemy.sql.select) -> sqlalchemy.sql.select
+```
+
+Applies the limit clause.
+
+**Arguments**:
+
+- `expr (sqlalchemy.sql.selectable.Select)`: query to modify
+
+**Returns**:
+
+`(sqlalchemy.sql.selectable.Select)`: modified query
+
diff --git a/docs/api/query-set/offset-query.md b/docs/api/query-set/offset-query.md
new file mode 100644
index 0000000..be6cf64
--- /dev/null
+++ b/docs/api/query-set/offset-query.md
@@ -0,0 +1,36 @@
+
+# queryset.offset\_query
+
+
+## OffsetQuery Objects
+
+```python
+class OffsetQuery()
+```
+
+Modifies the select query with offset if set
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(query_offset: Optional[int]) -> None
+```
+
+
+#### apply
+
+```python
+ | apply(expr: sqlalchemy.sql.select) -> sqlalchemy.sql.select
+```
+
+Applies the offset clause.
+
+**Arguments**:
+
+- `expr (sqlalchemy.sql.selectable.Select)`: query to modify
+
+**Returns**:
+
+`(sqlalchemy.sql.selectable.Select)`: modified query
+
diff --git a/docs/api/query-set/order-query.md b/docs/api/query-set/order-query.md
new file mode 100644
index 0000000..6927644
--- /dev/null
+++ b/docs/api/query-set/order-query.md
@@ -0,0 +1,36 @@
+
+# queryset.order\_query
+
+
+## OrderQuery Objects
+
+```python
+class OrderQuery()
+```
+
+Modifies the select query with given list of order_by clauses.
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(sorted_orders: Dict) -> None
+```
+
+
+#### apply
+
+```python
+ | apply(expr: sqlalchemy.sql.select) -> sqlalchemy.sql.select
+```
+
+Applies all order_by clauses if set.
+
+**Arguments**:
+
+- `expr (sqlalchemy.sql.selectable.Select)`: query to modify
+
+**Returns**:
+
+`(sqlalchemy.sql.selectable.Select)`: modified query
+
diff --git a/docs/api/query-set/prefetch-query.md b/docs/api/query-set/prefetch-query.md
new file mode 100644
index 0000000..102fdf5
--- /dev/null
+++ b/docs/api/query-set/prefetch-query.md
@@ -0,0 +1,352 @@
+
+# queryset.prefetch\_query
+
+
+#### add\_relation\_field\_to\_fields
+
+```python
+add_relation_field_to_fields(fields: Union[Set[Any], Dict[Any, Any], None], related_field_name: str) -> Union[Set[Any], Dict[Any, Any], None]
+```
+
+Adds related field into fields to include as otherwise it would be skipped.
+Related field is added only if fields are already populated.
+Empty fields implies all fields.
+
+**Arguments**:
+
+- `fields (Dict)`: Union[Set[Any], Dict[Any, Any], None]
+- `related_field_name (str)`: name of the field with relation
+
+**Returns**:
+
+`(Union[Set[Any], Dict[Any, Any], None])`: updated fields dict
+
+
+#### sort\_models
+
+```python
+sort_models(models: List["Model"], orders_by: Dict) -> List["Model"]
+```
+
+Since prefetch query gets all related models by ids the sorting needs to happen in
+python. Since by default models are already sorted by id here we resort only if
+order_by parameters was set.
+
+**Arguments**:
+
+- `models (List[tests.test_prefetch_related.Division])`: list of models already fetched from db
+- `orders_by (Dict[str, str])`: order by dictionary
+
+**Returns**:
+
+`(List[tests.test_prefetch_related.Division])`: sorted list of models
+
+
+#### set\_children\_on\_model
+
+```python
+set_children_on_model(model: "Model", related: str, children: Dict, model_id: int, models: Dict, orders_by: Dict) -> None
+```
+
+Extract ids of child models by given relation id key value.
+
+Based on those ids the actual children model instances are fetched from
+already fetched data.
+
+If needed the child models are resorted according to passed orders_by dict.
+
+Also relation is registered as each child is set as parent related field name value.
+
+**Arguments**:
+
+- `model (Model)`: parent model instance
+- `related (str)`: name of the related field
+- `children (Dict[int, set])`: dictionary of children ids/ related field value
+- `model_id (int)`: id of the model on which children should be set
+- `models (Dict)`: dictionary of child models instances
+- `orders_by (Dict)`: order_by dictionary
+
+
+## PrefetchQuery Objects
+
+```python
+class PrefetchQuery()
+```
+
+Query used to fetch related models in subsequent queries.
+Each model is fetched only ones by the name of the relation.
+That means that for each prefetch_related entry next query is issued to database.
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(model_cls: Type["Model"], fields: Optional[Union[Dict, Set]], exclude_fields: Optional[Union[Dict, Set]], prefetch_related: List, select_related: List, orders_by: List) -> None
+```
+
+
+#### prefetch\_related
+
+```python
+ | async prefetch_related(models: Sequence["Model"], rows: List) -> Sequence["Model"]
+```
+
+Main entry point for prefetch_query.
+
+Receives list of already initialized parent models with all children from
+select_related already populated. Receives also list of row sql result rows
+as it's quicker to extract ids that way instead of calling each model.
+
+Returns list with related models already prefetched and set.
+
+**Arguments**:
+
+- `models (List[Model])`: list of already instantiated models from main query
+- `rows (List[sqlalchemy.engine.result.RowProxy])`: row sql result of the main query before the prefetch
+
+**Returns**:
+
+`(List[Model])`: list of models with children prefetched
+
+
+#### \_extract\_ids\_from\_raw\_data
+
+```python
+ | _extract_ids_from_raw_data(parent_model: Type["Model"], column_name: str) -> Set
+```
+
+Iterates over raw rows and extract id values of relation columns by using
+prefixed column name.
+
+**Arguments**:
+
+- `parent_model (Type[Model])`: ormar model class
+- `column_name (str)`: name of the relation column which is a key column
+
+**Returns**:
+
+`(set)`: set of ids of related model that should be extracted
+
+
+#### \_extract\_ids\_from\_preloaded\_models
+
+```python
+ | _extract_ids_from_preloaded_models(parent_model: Type["Model"], column_name: str) -> Set
+```
+
+Extracts relation ids from already populated models if they were included
+in the original query before.
+
+**Arguments**:
+
+- `parent_model (Type["Model"])`: model from which related ids should be extracted
+- `column_name (str)`: name of the relation column which is a key column
+
+**Returns**:
+
+`(set)`: set of ids of related model that should be extracted
+
+
+#### \_extract\_required\_ids
+
+```python
+ | _extract_required_ids(parent_model: Type["Model"], reverse: bool, related: str) -> Set
+```
+
+Delegates extraction of the fields to either get ids from raw sql response
+or from already populated models.
+
+**Arguments**:
+
+- `parent_model (Type["Model"])`: model from which related ids should be extracted
+- `reverse (bool)`: flag if the relation is reverse
+- `related (str)`: name of the field with relation
+
+**Returns**:
+
+`(set)`: set of ids of related model that should be extracted
+
+
+#### \_get\_filter\_for\_prefetch
+
+```python
+ | _get_filter_for_prefetch(parent_model: Type["Model"], target_model: Type["Model"], reverse: bool, related: str) -> List
+```
+
+Populates where clause with condition to return only models within the
+set of extracted ids.
+
+If there are no ids for relation the empty list is returned.
+
+**Arguments**:
+
+- `parent_model (Type["Model"])`: model from which related ids should be extracted
+- `target_model (Type["Model"])`: model to which relation leads to
+- `reverse (bool)`: flag if the relation is reverse
+- `related (str)`: name of the field with relation
+
+**Returns**:
+
+`(List[sqlalchemy.sql.elements.TextClause])`:
+
+
+#### \_populate\_nested\_related
+
+```python
+ | _populate_nested_related(model: "Model", prefetch_dict: Dict, orders_by: Dict) -> "Model"
+```
+
+Populates all related models children of parent model that are
+included in prefetch query.
+
+**Arguments**:
+
+- `model (Model)`: ormar model instance
+- `prefetch_dict (Dict)`: dictionary of models to prefetch
+- `orders_by (Dict)`: dictionary of order bys
+
+**Returns**:
+
+`(Model)`: model with children populated
+
+
+#### \_prefetch\_related\_models
+
+```python
+ | async _prefetch_related_models(models: Sequence["Model"], rows: List) -> Sequence["Model"]
+```
+
+Main method of the query.
+
+Translates select nad prefetch list into dictionaries to avoid querying the
+same related models multiple times.
+
+Keeps the list of already extracted models.
+
+Extracts the related models from the database and later populate all children
+on each of the parent models from list.
+
+**Arguments**:
+
+- `models (List[Model])`: list of parent models from main query
+- `rows (List[sqlalchemy.engine.result.RowProxy])`: raw response from sql query
+
+**Returns**:
+
+`(List[Model])`: list of models with prefetch children populated
+
+
+#### \_extract\_related\_models
+
+```python
+ | async _extract_related_models(related: str, target_model: Type["Model"], prefetch_dict: Dict, select_dict: Dict, fields: Union[Set[Any], Dict[Any, Any], None], exclude_fields: Union[Set[Any], Dict[Any, Any], None], orders_by: Dict) -> None
+```
+
+Constructs queries with required ids and extracts data with fields that should
+be included/excluded.
+
+Runs the queries against the database and populated dictionaries with ids and
+with actual extracted children models.
+
+Calls itself recurrently to extract deeper nested relations of related model.
+
+**Arguments**:
+
+- `related (str)`: name of the relation
+- `target_model (Type[Model])`: model to which relation leads to
+- `prefetch_dict (Dict)`: prefetch related list converted into dictionary
+- `select_dict (Dict)`: select related list converted into dictionary
+- `fields (Union[Set[Any], Dict[Any, Any], None])`: fields to include
+- `exclude_fields (Union[Set[Any], Dict[Any, Any], None])`: fields to exclude
+- `orders_by (Dict)`: dictionary of order bys clauses
+
+**Returns**:
+
+`(None)`: None
+
+
+#### \_run\_prefetch\_query
+
+```python
+ | async _run_prefetch_query(target_field: Type["BaseField"], fields: Union[Set[Any], Dict[Any, Any], None], exclude_fields: Union[Set[Any], Dict[Any, Any], None], filter_clauses: List) -> Tuple[str, List]
+```
+
+Actually runs the queries against the database and populates the raw response
+for given related model.
+
+Returns table prefix as it's later needed to eventually initialize the children
+models.
+
+**Arguments**:
+
+- `target_field (Type["BaseField"])`: ormar field with relation definition
+- `fields (Union[Set[Any], Dict[Any, Any], None])`: fields to include
+- `exclude_fields (Union[Set[Any], Dict[Any, Any], None])`: fields to exclude
+- `filter_clauses (List[sqlalchemy.sql.elements.TextClause])`: list of clauses, actually one clause with ids of relation
+
+**Returns**:
+
+`(Tuple[str, List])`: table prefix and raw rows from sql response
+
+
+#### \_get\_select\_related\_if\_apply
+
+```python
+ | @staticmethod
+ | _get_select_related_if_apply(related: str, select_dict: Dict) -> Dict
+```
+
+Extract nested part of select_related dictionary to extract models nested
+deeper on related model and already loaded in select related query.
+
+**Arguments**:
+
+- `related (str)`: name of the relation
+- `select_dict (Dict)`: dictionary of select related models in main query
+
+**Returns**:
+
+`(Dict)`: dictionary with nested part of select related
+
+
+#### \_update\_already\_loaded\_rows
+
+```python
+ | _update_already_loaded_rows(target_field: Type["BaseField"], prefetch_dict: Dict, orders_by: Dict) -> None
+```
+
+Updates models that are already loaded, usually children of children.
+
+**Arguments**:
+
+- `target_field (Type["BaseField"])`: ormar field with relation definition
+- `prefetch_dict (Dict)`: dictionaries of related models to prefetch
+- `orders_by (Dict)`: dictionary of order by clauses by model
+
+
+#### \_populate\_rows
+
+```python
+ | _populate_rows(rows: List, target_field: Type["BaseField"], parent_model: Type["Model"], table_prefix: str, fields: Union[Set[Any], Dict[Any, Any], None], exclude_fields: Union[Set[Any], Dict[Any, Any], None], prefetch_dict: Dict, orders_by: Dict) -> None
+```
+
+Instantiates children models extracted from given relation.
+
+Populates them with their own nested children if they are included in prefetch
+query.
+
+Sets the initialized models and ids of them under corresponding keys in
+already_extracted dictionary. Later those instances will be fetched by ids
+and set on the parent model after sorting if needed.
+
+**Arguments**:
+
+- `rows (List[sqlalchemy.engine.result.RowProxy])`: raw sql response from the prefetch query
+- `target_field (Type["BaseField"])`: field with relation definition from parent model
+- `parent_model (Type[Model])`: model with relation definition
+- `table_prefix (str)`: prefix of the target table from current relation
+- `fields (Union[Set[Any], Dict[Any, Any], None])`: fields to include
+- `exclude_fields (Union[Set[Any], Dict[Any, Any], None])`: fields to exclude
+- `prefetch_dict (Dict)`: dictionaries of related models to prefetch
+- `orders_by (Dict)`: dictionary of order by clauses by model
+
diff --git a/docs/api/query-set/query-set.md b/docs/api/query-set/query-set.md
new file mode 100644
index 0000000..e572a09
--- /dev/null
+++ b/docs/api/query-set/query-set.md
@@ -0,0 +1,671 @@
+
+# queryset.queryset
+
+
+## QuerySet Objects
+
+```python
+class QuerySet()
+```
+
+Main class to perform database queries, exposed on each model as objects attribute.
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(model_cls: Type["Model"] = None, filter_clauses: List = None, exclude_clauses: List = None, select_related: List = None, limit_count: int = None, offset: int = None, columns: Dict = None, exclude_columns: Dict = None, order_bys: List = None, prefetch_related: List = None, limit_raw_sql: bool = False) -> None
+```
+
+
+#### \_\_get\_\_
+
+```python
+ | __get__(instance: Optional[Union["QuerySet", "QuerysetProxy"]], owner: Union[Type["Model"], Type["QuerysetProxy"]]) -> "QuerySet"
+```
+
+
+#### model\_meta
+
+```python
+ | @property
+ | model_meta() -> "ModelMeta"
+```
+
+Shortcut to model class Meta set on QuerySet model.
+
+**Returns**:
+
+`(model Meta class)`: Meta class of the model
+
+
+#### model
+
+```python
+ | @property
+ | model() -> Type["Model"]
+```
+
+Shortcut to model class set on QuerySet.
+
+**Returns**:
+
+`(Type[Model])`: model class
+
+
+#### \_prefetch\_related\_models
+
+```python
+ | async _prefetch_related_models(models: Sequence[Optional["Model"]], rows: List) -> Sequence[Optional["Model"]]
+```
+
+Performs prefetch query for selected models names.
+
+**Arguments**:
+
+- `models (List[Model])`: list of already parsed main Models from main query
+- `rows (List[sqlalchemy.engine.result.RowProxy])`: database rows from main query
+
+**Returns**:
+
+`(List[Model])`: list of models with prefetch models populated
+
+
+#### \_process\_query\_result\_rows
+
+```python
+ | _process_query_result_rows(rows: List) -> Sequence[Optional["Model"]]
+```
+
+Process database rows and initialize ormar Model from each of the rows.
+
+**Arguments**:
+
+- `rows (List[sqlalchemy.engine.result.RowProxy])`: list of database rows from query result
+
+**Returns**:
+
+`(List[Model])`: list of models
+
+
+#### check\_single\_result\_rows\_count
+
+```python
+ | @staticmethod
+ | check_single_result_rows_count(rows: Sequence[Optional["Model"]]) -> None
+```
+
+Verifies if the result has one and only one row.
+
+**Arguments**:
+
+- `rows (List[Model])`: one element list of Models
+
+
+#### database
+
+```python
+ | @property
+ | database() -> databases.Database
+```
+
+Shortcut to models database from Meta class.
+
+**Returns**:
+
+`(databases.Database)`: database
+
+
+#### table
+
+```python
+ | @property
+ | table() -> sqlalchemy.Table
+```
+
+Shortcut to models table from Meta class.
+
+**Returns**:
+
+`(sqlalchemy.Table)`: database table
+
+
+#### build\_select\_expression
+
+```python
+ | build_select_expression(limit: int = None, offset: int = None, order_bys: List = None) -> sqlalchemy.sql.select
+```
+
+Constructs the actual database query used in the QuerySet.
+If any of the params is not passed the QuerySet own value is used.
+
+**Arguments**:
+
+- `limit (int)`: number to limit the query
+- `offset (int)`: number to offset by
+- `order_bys (List)`: list of order-by fields names
+
+**Returns**:
+
+`(sqlalchemy.sql.selectable.Select)`: built sqlalchemy select expression
+
+
+#### filter
+
+```python
+ | filter(_exclude: bool = False, **kwargs: Any) -> "QuerySet"
+```
+
+Allows you to filter by any `Model` attribute/field
+as well as to fetch instances, with a filter across an FK relationship.
+
+You can use special filter suffix to change the filter operands:
+
+* exact - like `album__name__exact='Malibu'` (exact match)
+* iexact - like `album__name__iexact='malibu'` (exact match case insensitive)
+* contains - like `album__name__contains='Mal'` (sql like)
+* icontains - like `album__name__icontains='mal'` (sql like case insensitive)
+* in - like `album__name__in=['Malibu', 'Barclay']` (sql in)
+* gt - like `position__gt=3` (sql >)
+* gte - like `position__gte=3` (sql >=)
+* lt - like `position__lt=3` (sql <)
+* lte - like `position__lte=3` (sql <=)
+* startswith - like `album__name__startswith='Mal'` (exact start match)
+* istartswith - like `album__name__istartswith='mal'` (case insensitive)
+* endswith - like `album__name__endswith='ibu'` (exact end match)
+* iendswith - like `album__name__iendswith='IBU'` (case insensitive)
+
+**Arguments**:
+
+- `_exclude (bool)`: flag if it should be exclude or filter
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(QuerySet)`: filtered QuerySet
+
+
+#### exclude
+
+```python
+ | exclude(**kwargs: Any) -> "QuerySet"
+```
+
+Works exactly the same as filter and all modifiers (suffixes) are the same,
+but returns a *not* condition.
+
+So if you use `filter(name='John')` which is `where name = 'John'` in SQL,
+the `exclude(name='John')` equals to `where name <> 'John'`
+
+Note that all conditions are joined so if you pass multiple values it
+becomes a union of conditions.
+
+`exclude(name='John', age>=35)` will become
+`where not (name='John' and age>=35)`
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(QuerySet)`: filtered QuerySet
+
+
+#### select\_related
+
+```python
+ | select_related(related: Union[List, str]) -> "QuerySet"
+```
+
+Allows to prefetch related models during the same query.
+
+**With `select_related` always only one query is run against the database**,
+meaning that one (sometimes complicated) join is generated and later nested
+models are processed in python.
+
+To fetch related model use `ForeignKey` names.
+
+To chain related `Models` relation use double underscores between names.
+
+**Arguments**:
+
+- `related (Union[List, str])`: list of relation field names, can be linked by '__' to nest
+
+**Returns**:
+
+`(QuerySet)`: QuerySet
+
+
+#### prefetch\_related
+
+```python
+ | prefetch_related(related: Union[List, str]) -> "QuerySet"
+```
+
+Allows to prefetch related models during query - but opposite to
+`select_related` each subsequent model is fetched in a separate database query.
+
+**With `prefetch_related` always one query per Model is run against the
+database**, meaning that you will have multiple queries executed one
+after another.
+
+To fetch related model use `ForeignKey` names.
+
+To chain related `Models` relation use double underscores between names.
+
+**Arguments**:
+
+- `related (Union[List, str])`: list of relation field names, can be linked by '__' to nest
+
+**Returns**:
+
+`(QuerySet)`: QuerySet
+
+
+#### fields
+
+```python
+ | fields(columns: Union[List, str, Set, Dict]) -> "QuerySet"
+```
+
+With `fields()` you can select subset of model columns to limit the data load.
+
+Note that `fields()` and `exclude_fields()` works both for main models
+(on normal queries like `get`, `all` etc.)
+as well as `select_related` and `prefetch_related`
+models (with nested notation).
+
+You can select specified fields by passing a `str, List[str], Set[str] or
+dict` with nested definition.
+
+To include related models use notation
+`{related_name}__{column}[__{optional_next} etc.]`.
+
+`fields()` can be called several times, building up the columns to select.
+
+If you include related models into `select_related()` call but you won't specify
+columns for those models in fields - implies a list of all fields for
+those nested models.
+
+Mandatory fields cannot be excluded as it will raise `ValidationError`,
+to exclude a field it has to be nullable.
+
+Pk column cannot be excluded - it's always auto added even if
+not explicitly included.
+
+You can also pass fields to include as dictionary or set.
+
+To mark a field as included in a dictionary use it's name as key
+and ellipsis as value.
+
+To traverse nested models use nested dictionaries.
+
+To include fields at last level instead of nested dictionary a set can be used.
+
+To include whole nested model specify model related field name and ellipsis.
+
+**Arguments**:
+
+- `columns (Union[List, str, Set, Dict])`: columns to include
+
+**Returns**:
+
+`(QuerySet)`: QuerySet
+
+
+#### exclude\_fields
+
+```python
+ | exclude_fields(columns: Union[List, str, Set, Dict]) -> "QuerySet"
+```
+
+With `exclude_fields()` you can select subset of model columns that will
+be excluded to limit the data load.
+
+It's the opposite of `fields()` method so check documentation above
+to see what options are available.
+
+Especially check above how you can pass also nested dictionaries
+and sets as a mask to exclude fields from whole hierarchy.
+
+Note that `fields()` and `exclude_fields()` works both for main models
+(on normal queries like `get`, `all` etc.)
+as well as `select_related` and `prefetch_related` models
+(with nested notation).
+
+Mandatory fields cannot be excluded as it will raise `ValidationError`,
+to exclude a field it has to be nullable.
+
+Pk column cannot be excluded - it's always auto added even
+if explicitly excluded.
+
+**Arguments**:
+
+- `columns (Union[List, str, Set, Dict])`: columns to exclude
+
+**Returns**:
+
+`(QuerySet)`: QuerySet
+
+
+#### order\_by
+
+```python
+ | order_by(columns: Union[List, str]) -> "QuerySet"
+```
+
+With `order_by()` you can order the results from database based on your
+choice of fields.
+
+You can provide a string with field name or list of strings with fields names.
+
+Ordering in sql will be applied in order of names you provide in order_by.
+
+By default if you do not provide ordering `ormar` explicitly orders by
+all primary keys
+
+If you are sorting by nested models that causes that the result rows are
+unsorted by the main model `ormar` will combine those children rows into
+one main model.
+
+The main model will never duplicate in the result
+
+To order by main model field just provide a field name
+
+To sort on nested models separate field names with dunder '__'.
+
+You can sort this way across all relation types -> `ForeignKey`,
+reverse virtual FK and `ManyToMany` fields.
+
+To sort in descending order provide a hyphen in front of the field name
+
+**Arguments**:
+
+- `columns (Union[List, str])`: columns by which models should be sorted
+
+**Returns**:
+
+`(QuerySet)`: QuerySet
+
+
+#### exists
+
+```python
+ | async exists() -> bool
+```
+
+Returns a bool value to confirm if there are rows matching the given criteria
+(applied with `filter` and `exclude` if set).
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+#### count
+
+```python
+ | async count() -> int
+```
+
+Returns number of rows matching the given criteria
+(applied with `filter` and `exclude` if set before).
+
+**Returns**:
+
+`(int)`: number of rows
+
+
+#### update
+
+```python
+ | async update(each: bool = False, **kwargs: Any) -> int
+```
+
+Updates the model table after applying the filters from kwargs.
+
+You have to either pass a filter to narrow down a query or explicitly pass
+each=True flag to affect whole table.
+
+**Arguments**:
+
+- `each (bool)`: flag if whole table should be affected if no filter is passed
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(int)`: number of updated rows
+
+
+#### delete
+
+```python
+ | async delete(each: bool = False, **kwargs: Any) -> int
+```
+
+Deletes from the model table after applying the filters from kwargs.
+
+You have to either pass a filter to narrow down a query or explicitly pass
+each=True flag to affect whole table.
+
+**Arguments**:
+
+- `each (bool)`: flag if whole table should be affected if no filter is passed
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(int)`: number of deleted rows
+
+
+#### limit
+
+```python
+ | limit(limit_count: int, limit_raw_sql: bool = None) -> "QuerySet"
+```
+
+You can limit the results to desired number of parent models.
+
+To limit the actual number of database query rows instead of number of main
+models use the `limit_raw_sql` parameter flag, and set it to `True`.
+
+**Arguments**:
+
+- `limit_raw_sql (bool)`: flag if raw sql should be limited
+- `limit_count (int)`: number of models to limit
+
+**Returns**:
+
+`(QuerySet)`: QuerySet
+
+
+#### offset
+
+```python
+ | offset(offset: int, limit_raw_sql: bool = None) -> "QuerySet"
+```
+
+You can also offset the results by desired number of main models.
+
+To offset the actual number of database query rows instead of number of main
+models use the `limit_raw_sql` parameter flag, and set it to `True`.
+
+**Arguments**:
+
+- `limit_raw_sql (bool)`: flag if raw sql should be offset
+- `offset (int)`: numbers of models to offset
+
+**Returns**:
+
+`(QuerySet)`: QuerySet
+
+
+#### first
+
+```python
+ | async first(**kwargs: Any) -> "Model"
+```
+
+Gets the first row from the db ordered by primary key column ascending.
+
+**Raises**:
+
+- `NoMatch`: if no rows are returned
+- `MultipleMatches`: if more than 1 row is returned.
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(Model)`: returned model
+
+
+#### get
+
+```python
+ | async get(**kwargs: Any) -> "Model"
+```
+
+Get's the first row from the db meeting the criteria set by kwargs.
+
+If no criteria set it will return the last row in db sorted by pk.
+
+Passing a criteria is actually calling filter(**kwargs) method described below.
+
+**Raises**:
+
+- `NoMatch`: if no rows are returned
+- `MultipleMatches`: if more than 1 row is returned.
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(Model)`: returned model
+
+
+#### get\_or\_create
+
+```python
+ | async get_or_create(**kwargs: Any) -> "Model"
+```
+
+Combination of create and get methods.
+
+Tries to get a row meeting the criteria fro kwargs
+and if `NoMatch` exception is raised
+it creates a new one with given kwargs.
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(Model)`: returned or created Model
+
+
+#### update\_or\_create
+
+```python
+ | async update_or_create(**kwargs: Any) -> "Model"
+```
+
+Updates the model, or in case there is no match in database creates a new one.
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(Model)`: updated or created model
+
+
+#### all
+
+```python
+ | async all(**kwargs: Any) -> Sequence[Optional["Model"]]
+```
+
+Returns all rows from a database for given model for set filter options.
+
+Passing kwargs is a shortcut and equals to calling `filter(**kwrags).all()`.
+
+If there are no rows meeting the criteria an empty list is returned.
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(List[Model])`: list of returned models
+
+
+#### create
+
+```python
+ | async create(**kwargs: Any) -> "Model"
+```
+
+Creates the model instance, saves it in a database and returns the updates model
+(with pk populated if not passed and autoincrement is set).
+
+The allowed kwargs are `Model` fields names and proper value types.
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(Model)`: created model
+
+
+#### bulk\_create
+
+```python
+ | async bulk_create(objects: List["Model"]) -> None
+```
+
+Performs a bulk update in one database session to speed up the process.
+
+Allows you to create multiple objects at once.
+
+A valid list of `Model` objects needs to be passed.
+
+Bulk operations do not send signals.
+
+**Arguments**:
+
+- `objects (List[Model])`: list of ormar models already initialized and ready to save.
+
+
+#### bulk\_update
+
+```python
+ | async bulk_update(objects: List["Model"], columns: List[str] = None) -> None
+```
+
+Performs bulk update in one database session to speed up the process.
+
+Allows to update multiple instance at once.
+
+All `Models` passed need to have primary key column populated.
+
+You can also select which fields to update by passing `columns` list
+as a list of string names.
+
+Bulk operations do not send signals.
+
+**Arguments**:
+
+- `objects (List[Model])`: list of ormar models
+- `columns (List[str])`: list of columns to update
+
diff --git a/docs/api/query-set/query.md b/docs/api/query-set/query.md
new file mode 100644
index 0000000..4166562
--- /dev/null
+++ b/docs/api/query-set/query.md
@@ -0,0 +1,157 @@
+
+# queryset.query
+
+
+## Query Objects
+
+```python
+class Query()
+```
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(model_cls: Type["Model"], filter_clauses: List, exclude_clauses: List, select_related: List, limit_count: Optional[int], offset: Optional[int], fields: Optional[Union[Dict, Set]], exclude_fields: Optional[Union[Dict, Set]], order_bys: Optional[List], limit_raw_sql: bool) -> None
+```
+
+
+#### \_init\_sorted\_orders
+
+```python
+ | _init_sorted_orders() -> None
+```
+
+Initialize empty order_by dict to be populated later during the query call
+
+
+#### prefixed\_pk\_name
+
+```python
+ | @property
+ | prefixed_pk_name() -> str
+```
+
+Shortcut for extracting prefixed with alias primary key column name from main
+model
+
+**Returns**:
+
+`(str)`: alias of pk column prefix with table name.
+
+
+#### alias
+
+```python
+ | alias(name: str) -> str
+```
+
+Shortcut to extracting column alias from given master model.
+
+**Arguments**:
+
+- `name (str)`: name of column
+
+**Returns**:
+
+`(str)`: alias of given column name
+
+
+#### apply\_order\_bys\_for\_primary\_model
+
+```python
+ | apply_order_bys_for_primary_model() -> None
+```
+
+Applies order_by queries on main model when it's used as a subquery.
+That way the subquery with limit and offset only on main model has proper
+sorting applied and correct models are fetched.
+
+
+#### \_pagination\_query\_required
+
+```python
+ | _pagination_query_required() -> bool
+```
+
+Checks if limit or offset are set, the flag limit_sql_raw is not set
+and query has select_related applied. Otherwise we can limit/offset normally
+at the end of whole query.
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+#### build\_select\_expression
+
+```python
+ | build_select_expression() -> Tuple[sqlalchemy.sql.select, List[str]]
+```
+
+Main entry point from outside (after proper initialization).
+
+Extracts columns list to fetch,
+construct all required joins for select related,
+then applies all conditional and sort clauses.
+
+Returns ready to run query with all joins and clauses.
+
+**Returns**:
+
+`(sqlalchemy.sql.selectable.Select)`: ready to run query with all joins and clauses.
+
+
+#### \_build\_pagination\_subquery
+
+```python
+ | _build_pagination_subquery() -> sqlalchemy.sql.select
+```
+
+In order to apply limit and offset on main table in join only
+(otherwise you can get only partially constructed main model
+if number of children exceeds the applied limit and select_related is used)
+
+Used also to change first and get() without argument behaviour.
+Needed only if limit or offset are set, the flag limit_sql_raw is not set
+and query has select_related applied. Otherwise we can limit/offset normally
+at the end of whole query.
+
+**Returns**:
+
+`(sqlalchemy.sql.select)`: constructed subquery on main table with limit, offset and order applied
+
+
+#### \_apply\_expression\_modifiers
+
+```python
+ | _apply_expression_modifiers(expr: sqlalchemy.sql.select) -> sqlalchemy.sql.select
+```
+
+Receives the select query (might be join) and applies:
+* Filter clauses
+* Exclude filter clauses
+* Limit clauses
+* Offset clauses
+* Order by clauses
+
+Returns complete ready to run query.
+
+**Arguments**:
+
+- `expr (sqlalchemy.sql.selectable.Select)`: select expression before clauses
+
+**Returns**:
+
+`(sqlalchemy.sql.selectable.Select)`: expresion with all present clauses applied
+
+
+#### \_reset\_query\_parameters
+
+```python
+ | _reset_query_parameters() -> None
+```
+
+Although it should be created each time before the call we reset the key params
+anyway.
+
diff --git a/docs/api/query-set/utils.md b/docs/api/query-set/utils.md
new file mode 100644
index 0000000..27989a3
--- /dev/null
+++ b/docs/api/query-set/utils.md
@@ -0,0 +1,152 @@
+
+# queryset.utils
+
+
+#### check\_node\_not\_dict\_or\_not\_last\_node
+
+```python
+check_node_not_dict_or_not_last_node(part: str, parts: List, current_level: Any) -> bool
+```
+
+Checks if given name is not present in the current level of the structure.
+Checks if given name is not the last name in the split list of parts.
+Checks if the given name in current level is not a dictionary.
+
+All those checks verify if there is a need for deeper traversal.
+
+**Arguments**:
+
+- `part (str)`:
+- `parts (List[str])`:
+- `current_level (Any)`: current level of the traversed structure
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+#### translate\_list\_to\_dict
+
+```python
+translate_list_to_dict(list_to_trans: Union[List, Set], is_order: bool = False) -> Dict
+```
+
+Splits the list of strings by '__' and converts them to dictionary with nested
+models grouped by parent model. That way each model appears only once in the whole
+dictionary and children are grouped under parent name.
+
+Default required key ise Ellipsis like in pydantic.
+
+**Arguments**:
+
+- `list_to_trans (set)`: input list
+- `is_order (bool)`: flag if change affects order_by clauses are they require special
+default value with sort order.
+
+**Returns**:
+
+`(Dict)`: converted to dictionary input list
+
+
+#### convert\_set\_to\_required\_dict
+
+```python
+convert_set_to_required_dict(set_to_convert: set) -> Dict
+```
+
+Converts set to dictionary of required keys.
+Required key is Ellipsis.
+
+**Arguments**:
+
+- `set_to_convert (set)`: set to convert to dict
+
+**Returns**:
+
+`(Dict)`: set converted to dict of ellipsis
+
+
+#### update
+
+```python
+update(current_dict: Any, updating_dict: Any) -> Dict
+```
+
+Update one dict with another but with regard for nested keys.
+
+That way nested sets are unionised, dicts updated and
+only other values are overwritten.
+
+**Arguments**:
+
+- `current_dict (Dict[str, ellipsis])`: dict to update
+- `updating_dict (Dict)`: dict with values to update
+
+**Returns**:
+
+`(Dict)`: combination of both dicts
+
+
+#### update\_dict\_from\_list
+
+```python
+update_dict_from_list(curr_dict: Dict, list_to_update: Union[List, Set]) -> Dict
+```
+
+Converts the list into dictionary and later performs special update, where
+nested keys that are sets or dicts are combined and not overwritten.
+
+**Arguments**:
+
+- `curr_dict (Dict)`: dict to update
+- `list_to_update (List[str])`: list with values to update the dict
+
+**Returns**:
+
+`(Dict)`: updated dict
+
+
+#### extract\_nested\_models
+
+```python
+extract_nested_models(model: "Model", model_type: Type["Model"], select_dict: Dict, extracted: Dict) -> None
+```
+
+Iterates over model relations and extracts all nested models from select_dict and
+puts them in corresponding list under relation name in extracted dict.keys
+
+Basically flattens all relation to dictionary of all related models, that can be
+used on several models and extract all of their children into dictionary of lists
+witch children models.
+
+Goes also into nested relations if needed (specified in select_dict).
+
+**Arguments**:
+
+- `model (Model)`: parent Model
+- `model_type (Type[Model])`: parent model class
+- `select_dict (Dict)`: dictionary of related models from select_related
+- `extracted (Dict)`: dictionary with already extracted models
+
+
+#### extract\_models\_to\_dict\_of\_lists
+
+```python
+extract_models_to_dict_of_lists(model_type: Type["Model"], models: Sequence["Model"], select_dict: Dict, extracted: Dict = None) -> Dict
+```
+
+Receives a list of models and extracts all of the children and their children
+into dictionary of lists with children models, flattening the structure to one dict
+with all children models under their relation keys.
+
+**Arguments**:
+
+- `model_type (Type[Model])`: parent model class
+- `models (List[Model])`: list of models from which related models should be extracted.
+- `select_dict (Dict)`: dictionary of related models from select_related
+- `extracted (Dict)`: dictionary with already extracted models
+
+**Returns**:
+
+`(Dict)`: dictionary of lists f related models
+
diff --git a/docs/api/relations/alias-manager.md b/docs/api/relations/alias-manager.md
new file mode 100644
index 0000000..4ffffe9
--- /dev/null
+++ b/docs/api/relations/alias-manager.md
@@ -0,0 +1,127 @@
+
+# relations.alias\_manager
+
+
+#### get\_table\_alias
+
+```python
+get_table_alias() -> str
+```
+
+Creates a random string that is used to alias tables in joins.
+It's necessary that each relation has it's own aliases cause you can link
+to the same target tables from multiple fields on one model as well as from
+multiple different models in one join.
+
+**Returns**:
+
+`(str)`: randomly generated alias
+
+
+## AliasManager Objects
+
+```python
+class AliasManager()
+```
+
+Keep all aliases of relations between different tables.
+One global instance is shared between all models.
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__() -> None
+```
+
+
+#### prefixed\_columns
+
+```python
+ | @staticmethod
+ | prefixed_columns(alias: str, table: sqlalchemy.Table, fields: List = None) -> List[text]
+```
+
+Creates a list of aliases sqlalchemy text clauses from
+string alias and sqlalchemy.Table.
+
+Optional list of fields to include can be passed to extract only those columns.
+List has to have sqlalchemy names of columns (ormar aliases) not the ormar ones.
+
+**Arguments**:
+
+- `alias (str)`: alias of given table
+- `table (sqlalchemy.Table)`: table from which fields should be aliased
+- `fields (Optional[List[str]])`: fields to include
+
+**Returns**:
+
+`(List[text])`: list of sqlalchemy text clauses with "column name as aliased name"
+
+
+#### prefixed\_table\_name
+
+```python
+ | @staticmethod
+ | prefixed_table_name(alias: str, name: str) -> text
+```
+
+Creates text clause with table name with aliased name.
+
+**Arguments**:
+
+- `alias (str)`: alias of given table
+- `name (str)`: table name
+
+**Returns**:
+
+`(sqlalchemy text clause)`: sqlalchemy text clause as "table_name aliased_name"
+
+
+#### add\_relation\_type
+
+```python
+ | add_relation_type(source_model: Type["Model"], relation_name: str, reverse_name: str = None, is_multi: bool = False) -> None
+```
+
+Registers the relations defined in ormar models.
+Given the relation it registers also the reverse side of this relation.
+
+Used by both ForeignKey and ManyToMany relations.
+
+Each relation is registered as Model name and relation name.
+Each alias registered has to be unique.
+
+Aliases are used to construct joins to assure proper links between tables.
+That way you can link to the same target tables from multiple fields
+on one model as well as from multiple different models in one join.
+
+**Arguments**:
+
+- `source_model (source Model)`: model with relation defined
+- `relation_name (str)`: name of the relation to define
+- `reverse_name (Optional[str])`: name of related_name fo given relation for m2m relations
+- `is_multi (bool)`: flag if relation being registered is a through m2m model
+
+**Returns**:
+
+`(None)`: none
+
+
+#### resolve\_relation\_alias
+
+```python
+ | resolve_relation_alias(from_model: Type["Model"], relation_name: str) -> str
+```
+
+Given model and relation name returns the alias for this relation.
+
+**Arguments**:
+
+- `from_model (source Model)`: model with relation defined
+- `relation_name (str)`: name of the relation field
+
+**Returns**:
+
+`(str)`: alias of the relation
+
diff --git a/docs/api/relations/queryset-proxy.md b/docs/api/relations/queryset-proxy.md
new file mode 100644
index 0000000..38cabb2
--- /dev/null
+++ b/docs/api/relations/queryset-proxy.md
@@ -0,0 +1,595 @@
+
+# relations.querysetproxy
+
+
+## QuerysetProxy Objects
+
+```python
+class QuerysetProxy(ormar.QuerySetProtocol)
+```
+
+Exposes QuerySet methods on relations, but also handles creating and removing
+of through Models for m2m relations.
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(relation: "Relation", type_: "RelationType", qryset: "QuerySet" = None) -> None
+```
+
+
+#### queryset
+
+```python
+ | @property
+ | queryset() -> "QuerySet"
+```
+
+Returns queryset if it's set, AttributeError otherwise.
+
+**Returns**:
+
+`(QuerySet)`: QuerySet
+
+
+#### queryset
+
+```python
+ | @queryset.setter
+ | queryset(value: "QuerySet") -> None
+```
+
+Set's the queryset. Initialized in RelationProxy.
+
+**Arguments**:
+
+- `value (QuerySet)`: QuerySet
+
+
+#### \_assign\_child\_to\_parent
+
+```python
+ | _assign_child_to_parent(child: Optional["T"]) -> None
+```
+
+Registers child in parents RelationManager.
+
+**Arguments**:
+
+- `child (Model)`: child to register on parent side.
+
+
+#### \_register\_related
+
+```python
+ | _register_related(child: Union["T", Sequence[Optional["T"]]]) -> None
+```
+
+Registers child/ children in parents RelationManager.
+
+**Arguments**:
+
+- `child (Union[Model,List[Model]])`: child or list of children models to register.
+
+
+#### \_clean\_items\_on\_load
+
+```python
+ | _clean_items_on_load() -> None
+```
+
+Cleans the current list of the related models.
+
+
+#### create\_through\_instance
+
+```python
+ | async create_through_instance(child: "T") -> None
+```
+
+Crete a through model instance in the database for m2m relations.
+
+**Arguments**:
+
+- `child (Model)`: child model instance
+
+
+#### delete\_through\_instance
+
+```python
+ | async delete_through_instance(child: "T") -> None
+```
+
+Removes through model instance from the database for m2m relations.
+
+**Arguments**:
+
+- `child (Model)`: child model instance
+
+
+#### exists
+
+```python
+ | async exists() -> bool
+```
+
+Returns a bool value to confirm if there are rows matching the given criteria
+(applied with `filter` and `exclude` if set).
+
+Actual call delegated to QuerySet.
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+#### count
+
+```python
+ | async count() -> int
+```
+
+Returns number of rows matching the given criteria
+(applied with `filter` and `exclude` if set before).
+
+Actual call delegated to QuerySet.
+
+**Returns**:
+
+`(int)`: number of rows
+
+
+#### clear
+
+```python
+ | async clear(keep_reversed: bool = True) -> int
+```
+
+Removes all related models from given relation.
+
+Removes all through models for m2m relation.
+
+For reverse FK relations keep_reversed flag marks if the reversed models
+should be kept or deleted from the database too (False means that models
+will be deleted, and not only removed from relation).
+
+**Arguments**:
+
+- `keep_reversed (bool)`: flag if reverse models in reverse FK should be deleted
+or not, keep_reversed=False deletes them from database.
+
+**Returns**:
+
+`(int)`: number of deleted models
+
+
+#### first
+
+```python
+ | async first(**kwargs: Any) -> "Model"
+```
+
+Gets the first row from the db ordered by primary key column ascending.
+
+Actual call delegated to QuerySet.
+
+List of related models is cleared before the call.
+
+**Arguments**:
+
+- `kwargs ()`:
+
+**Returns**:
+
+`(_asyncio.Future)`:
+
+
+#### get
+
+```python
+ | async get(**kwargs: Any) -> "Model"
+```
+
+Get's the first row from the db meeting the criteria set by kwargs.
+
+If no criteria set it will return the last row in db sorted by pk.
+
+Passing a criteria is actually calling filter(**kwargs) method described below.
+
+Actual call delegated to QuerySet.
+
+List of related models is cleared before the call.
+
+**Raises**:
+
+- `NoMatch`: if no rows are returned
+- `MultipleMatches`: if more than 1 row is returned.
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(Model)`: returned model
+
+
+#### all
+
+```python
+ | async all(**kwargs: Any) -> Sequence[Optional["Model"]]
+```
+
+Returns all rows from a database for given model for set filter options.
+
+Passing kwargs is a shortcut and equals to calling `filter(**kwrags).all()`.
+
+If there are no rows meeting the criteria an empty list is returned.
+
+Actual call delegated to QuerySet.
+
+List of related models is cleared before the call.
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(List[Model])`: list of returned models
+
+
+#### create
+
+```python
+ | async create(**kwargs: Any) -> "Model"
+```
+
+Creates the model instance, saves it in a database and returns the updates model
+(with pk populated if not passed and autoincrement is set).
+
+The allowed kwargs are `Model` fields names and proper value types.
+
+For m2m relation the through model is created automatically.
+
+Actual call delegated to QuerySet.
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(Model)`: created model
+
+
+#### get\_or\_create
+
+```python
+ | async get_or_create(**kwargs: Any) -> "Model"
+```
+
+Combination of create and get methods.
+
+Tries to get a row meeting the criteria fro kwargs
+and if `NoMatch` exception is raised
+it creates a new one with given kwargs.
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(Model)`: returned or created Model
+
+
+#### update\_or\_create
+
+```python
+ | async update_or_create(**kwargs: Any) -> "Model"
+```
+
+Updates the model, or in case there is no match in database creates a new one.
+
+Actual call delegated to QuerySet.
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(Model)`: updated or created model
+
+
+#### filter
+
+```python
+ | filter(**kwargs: Any) -> "QuerysetProxy"
+```
+
+Allows you to filter by any `Model` attribute/field
+as well as to fetch instances, with a filter across an FK relationship.
+
+You can use special filter suffix to change the filter operands:
+
+* exact - like `album__name__exact='Malibu'` (exact match)
+* iexact - like `album__name__iexact='malibu'` (exact match case insensitive)
+* contains - like `album__name__contains='Mal'` (sql like)
+* icontains - like `album__name__icontains='mal'` (sql like case insensitive)
+* in - like `album__name__in=['Malibu', 'Barclay']` (sql in)
+* gt - like `position__gt=3` (sql >)
+* gte - like `position__gte=3` (sql >=)
+* lt - like `position__lt=3` (sql <)
+* lte - like `position__lte=3` (sql <=)
+* startswith - like `album__name__startswith='Mal'` (exact start match)
+* istartswith - like `album__name__istartswith='mal'` (case insensitive)
+* endswith - like `album__name__endswith='ibu'` (exact end match)
+* iendswith - like `album__name__iendswith='IBU'` (case insensitive)
+
+Actual call delegated to QuerySet.
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(QuerysetProxy)`: filtered QuerysetProxy
+
+
+#### exclude
+
+```python
+ | exclude(**kwargs: Any) -> "QuerysetProxy"
+```
+
+Works exactly the same as filter and all modifiers (suffixes) are the same,
+but returns a *not* condition.
+
+So if you use `filter(name='John')` which is `where name = 'John'` in SQL,
+the `exclude(name='John')` equals to `where name <> 'John'`
+
+Note that all conditions are joined so if you pass multiple values it
+becomes a union of conditions.
+
+`exclude(name='John', age>=35)` will become
+`where not (name='John' and age>=35)`
+
+Actual call delegated to QuerySet.
+
+**Arguments**:
+
+- `kwargs (Any)`: fields names and proper value types
+
+**Returns**:
+
+`(QuerysetProxy)`: filtered QuerysetProxy
+
+
+#### select\_related
+
+```python
+ | select_related(related: Union[List, str]) -> "QuerysetProxy"
+```
+
+Allows to prefetch related models during the same query.
+
+**With `select_related` always only one query is run against the database**,
+meaning that one (sometimes complicated) join is generated and later nested
+models are processed in python.
+
+To fetch related model use `ForeignKey` names.
+
+To chain related `Models` relation use double underscores between names.
+
+Actual call delegated to QuerySet.
+
+**Arguments**:
+
+- `related (Union[List, str])`: list of relation field names, can be linked by '__' to nest
+
+**Returns**:
+
+`(QuerysetProxy)`: QuerysetProxy
+
+
+#### prefetch\_related
+
+```python
+ | prefetch_related(related: Union[List, str]) -> "QuerysetProxy"
+```
+
+Allows to prefetch related models during query - but opposite to
+`select_related` each subsequent model is fetched in a separate database query.
+
+**With `prefetch_related` always one query per Model is run against the
+database**, meaning that you will have multiple queries executed one
+after another.
+
+To fetch related model use `ForeignKey` names.
+
+To chain related `Models` relation use double underscores between names.
+
+Actual call delegated to QuerySet.
+
+**Arguments**:
+
+- `related (Union[List, str])`: list of relation field names, can be linked by '__' to nest
+
+**Returns**:
+
+`(QuerysetProxy)`: QuerysetProxy
+
+
+#### limit
+
+```python
+ | limit(limit_count: int) -> "QuerysetProxy"
+```
+
+You can limit the results to desired number of parent models.
+
+Actual call delegated to QuerySet.
+
+**Arguments**:
+
+- `limit_count (int)`: number of models to limit
+
+**Returns**:
+
+`(QuerysetProxy)`: QuerysetProxy
+
+
+#### offset
+
+```python
+ | offset(offset: int) -> "QuerysetProxy"
+```
+
+You can also offset the results by desired number of main models.
+
+Actual call delegated to QuerySet.
+
+**Arguments**:
+
+- `offset (int)`: numbers of models to offset
+
+**Returns**:
+
+`(QuerysetProxy)`: QuerysetProxy
+
+
+#### fields
+
+```python
+ | fields(columns: Union[List, str, Set, Dict]) -> "QuerysetProxy"
+```
+
+With `fields()` you can select subset of model columns to limit the data load.
+
+Note that `fields()` and `exclude_fields()` works both for main models
+(on normal queries like `get`, `all` etc.)
+as well as `select_related` and `prefetch_related`
+models (with nested notation).
+
+You can select specified fields by passing a `str, List[str], Set[str] or
+dict` with nested definition.
+
+To include related models use notation
+`{related_name}__{column}[__{optional_next} etc.]`.
+
+`fields()` can be called several times, building up the columns to select.
+
+If you include related models into `select_related()` call but you won't specify
+columns for those models in fields - implies a list of all fields for
+those nested models.
+
+Mandatory fields cannot be excluded as it will raise `ValidationError`,
+to exclude a field it has to be nullable.
+
+Pk column cannot be excluded - it's always auto added even if
+not explicitly included.
+
+You can also pass fields to include as dictionary or set.
+
+To mark a field as included in a dictionary use it's name as key
+and ellipsis as value.
+
+To traverse nested models use nested dictionaries.
+
+To include fields at last level instead of nested dictionary a set can be used.
+
+To include whole nested model specify model related field name and ellipsis.
+
+Actual call delegated to QuerySet.
+
+**Arguments**:
+
+- `columns (Union[List, str, Set, Dict])`: columns to include
+
+**Returns**:
+
+`(QuerysetProxy)`: QuerysetProxy
+
+
+#### exclude\_fields
+
+```python
+ | exclude_fields(columns: Union[List, str, Set, Dict]) -> "QuerysetProxy"
+```
+
+With `exclude_fields()` you can select subset of model columns that will
+be excluded to limit the data load.
+
+It's the opposite of `fields()` method so check documentation above
+to see what options are available.
+
+Especially check above how you can pass also nested dictionaries
+and sets as a mask to exclude fields from whole hierarchy.
+
+Note that `fields()` and `exclude_fields()` works both for main models
+(on normal queries like `get`, `all` etc.)
+as well as `select_related` and `prefetch_related` models
+(with nested notation).
+
+Mandatory fields cannot be excluded as it will raise `ValidationError`,
+to exclude a field it has to be nullable.
+
+Pk column cannot be excluded - it's always auto added even
+if explicitly excluded.
+
+Actual call delegated to QuerySet.
+
+**Arguments**:
+
+- `columns (Union[List, str, Set, Dict])`: columns to exclude
+
+**Returns**:
+
+`(QuerysetProxy)`: QuerysetProxy
+
+
+#### order\_by
+
+```python
+ | order_by(columns: Union[List, str]) -> "QuerysetProxy"
+```
+
+With `order_by()` you can order the results from database based on your
+choice of fields.
+
+You can provide a string with field name or list of strings with fields names.
+
+Ordering in sql will be applied in order of names you provide in order_by.
+
+By default if you do not provide ordering `ormar` explicitly orders by
+all primary keys
+
+If you are sorting by nested models that causes that the result rows are
+unsorted by the main model `ormar` will combine those children rows into
+one main model.
+
+The main model will never duplicate in the result
+
+To order by main model field just provide a field name
+
+To sort on nested models separate field names with dunder '__'.
+
+You can sort this way across all relation types -> `ForeignKey`,
+reverse virtual FK and `ManyToMany` fields.
+
+To sort in descending order provide a hyphen in front of the field name
+
+Actual call delegated to QuerySet.
+
+**Arguments**:
+
+- `columns (Union[List, str])`: columns by which models should be sorted
+
+**Returns**:
+
+`(QuerysetProxy)`: QuerysetProxy
+
diff --git a/docs/api/relations/relation-manager.md b/docs/api/relations/relation-manager.md
new file mode 100644
index 0000000..818bdd9
--- /dev/null
+++ b/docs/api/relations/relation-manager.md
@@ -0,0 +1,159 @@
+
+# relations.relation\_manager
+
+
+## RelationsManager Objects
+
+```python
+class RelationsManager()
+```
+
+Manages relations on a Model, each Model has it's own instance.
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(related_fields: List[Type[ForeignKeyField]] = None, owner: "NewBaseModel" = None) -> None
+```
+
+
+#### \_get\_relation\_type
+
+```python
+ | _get_relation_type(field: Type[BaseField]) -> RelationType
+```
+
+Returns type of the relation declared on a field.
+
+**Arguments**:
+
+- `field (Type[BaseField])`: field with relation declaration
+
+**Returns**:
+
+`(RelationType)`: type of the relation defined on field
+
+
+#### \_add\_relation
+
+```python
+ | _add_relation(field: Type[BaseField]) -> None
+```
+
+Registers relation in the manager.
+Adds Relation instance under field.name.
+
+**Arguments**:
+
+- `field (Type[BaseField])`: field with relation declaration
+
+
+#### \_\_contains\_\_
+
+```python
+ | __contains__(item: str) -> bool
+```
+
+Checks if relation with given name is already registered.
+
+**Arguments**:
+
+- `item (str)`: name of attribute
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+#### get
+
+```python
+ | get(name: str) -> Optional[Union["T", Sequence["T"]]]
+```
+
+Returns the related model/models if relation is set.
+Actual call is delegated to Relation instance registered under relation name.
+
+**Arguments**:
+
+- `name (str)`: name of the relation
+
+**Returns**:
+
+`(Optional[Union[Model, List[Model]])`: related model or list of related models if set
+
+
+#### \_get
+
+```python
+ | _get(name: str) -> Optional[Relation]
+```
+
+Returns the actual relation and not the related model(s).
+
+**Arguments**:
+
+- `name (str)`: name of the relation
+
+**Returns**:
+
+`(ormar.relations.relation.Relation)`: Relation instance
+
+
+#### add
+
+```python
+ | @staticmethod
+ | add(parent: "Model", child: "Model", child_name: str, virtual: bool, relation_name: str) -> None
+```
+
+Adds relation on both sides -> meaning on both child and parent models.
+One side of the relation is always weakref proxy to avoid circular refs.
+
+Based on the side from which relation is added and relation name actual names
+of parent and child relations are established. The related models are registered
+on both ends.
+
+**Arguments**:
+
+- `parent (Model)`: parent model on which relation should be registered
+- `child (Model)`: child model to register
+- `child_name (str)`: potential child name used if related name is not set
+- `virtual (bool)`:
+- `relation_name (str)`: name of the relation
+
+
+#### remove
+
+```python
+ | remove(name: str, child: Union["NewBaseModel", Type["NewBaseModel"]]) -> None
+```
+
+Removes given child from relation with given name.
+Since you can have many relations between two models you need to pass a name
+of relation from which you want to remove the child.
+
+**Arguments**:
+
+- `name (str)`: name of the relation
+- `child (Union[Model, Type[Model]])`: child to remove from relation
+
+
+#### remove\_parent
+
+```python
+ | @staticmethod
+ | remove_parent(item: Union["NewBaseModel", Type["NewBaseModel"]], parent: "Model", name: str) -> None
+```
+
+Removes given parent from relation with given name.
+Since you can have many relations between two models you need to pass a name
+of relation from which you want to remove the parent.
+
+**Arguments**:
+
+- `item (Union[Model, Type[Model]])`: model with parent registered
+- `parent (Model)`: parent Model
+- `name (str)`: name of the relation
+
diff --git a/docs/api/relations/relation-proxy.md b/docs/api/relations/relation-proxy.md
new file mode 100644
index 0000000..a25122a
--- /dev/null
+++ b/docs/api/relations/relation-proxy.md
@@ -0,0 +1,151 @@
+
+# relations.relation\_proxy
+
+
+## RelationProxy Objects
+
+```python
+class RelationProxy(list)
+```
+
+Proxy of the Relation that is a list with special methods.
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(relation: "Relation", type_: "RelationType", field_name: str, data_: Any = None) -> None
+```
+
+
+#### related\_field\_name
+
+```python
+ | @property
+ | related_field_name() -> str
+```
+
+On first access calculates the name of the related field, later stored in
+_related_field_name property.
+
+**Returns**:
+
+`(str)`: name of the related field
+
+
+#### \_\_getattribute\_\_
+
+```python
+ | __getattribute__(item: str) -> Any
+```
+
+Since some QuerySetProxy methods overwrite builtin list methods we
+catch calls to them and delegate it to QuerySetProxy instead.
+
+**Arguments**:
+
+- `item (str)`: name of attribute
+
+**Returns**:
+
+`(Any)`: value of attribute
+
+
+#### \_\_getattr\_\_
+
+```python
+ | __getattr__(item: str) -> Any
+```
+
+Delegates calls for non existing attributes to QuerySetProxy.
+
+**Arguments**:
+
+- `item (str)`: name of attribute/method
+
+**Returns**:
+
+`(method)`: method from QuerySetProxy if exists
+
+
+#### \_initialize\_queryset
+
+```python
+ | _initialize_queryset() -> None
+```
+
+Initializes the QuerySetProxy if not yet initialized.
+
+
+#### \_check\_if\_queryset\_is\_initialized
+
+```python
+ | _check_if_queryset_is_initialized() -> bool
+```
+
+Checks if the QuerySetProxy is already set and ready.
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+#### \_check\_if\_model\_saved
+
+```python
+ | _check_if_model_saved() -> None
+```
+
+Verifies if the parent model of the relation has been already saved.
+Otherwise QuerySetProxy cannot filter by parent primary key.
+
+
+#### \_set\_queryset
+
+```python
+ | _set_queryset() -> "QuerySet"
+```
+
+Creates new QuerySet with relation model and pre filters it with currents
+parent model primary key, so all queries by definition are already related
+to the parent model only, without need for user to filter them.
+
+**Returns**:
+
+`(QuerySet)`: initialized QuerySet
+
+
+#### remove
+
+```python
+ | async remove(item: "Model", keep_reversed: bool = True) -> None
+```
+
+Removes the item from relation with parent.
+
+Through models are automatically deleted for m2m relations.
+
+For reverse FK relations keep_reversed flag marks if the reversed models
+should be kept or deleted from the database too (False means that models
+will be deleted, and not only removed from relation).
+
+**Arguments**:
+
+- `item (Model)`: child to remove from relation
+- `keep_reversed (bool)`: flag if the reversed model should be kept or deleted too
+
+
+#### add
+
+```python
+ | async add(item: "Model") -> None
+```
+
+Adds child model to relation.
+
+For ManyToMany relations through instance is automatically created.
+
+**Arguments**:
+
+- `item (Model)`: child to add to relation
+
diff --git a/docs/api/relations/relation.md b/docs/api/relations/relation.md
new file mode 100644
index 0000000..141d1b3
--- /dev/null
+++ b/docs/api/relations/relation.md
@@ -0,0 +1,128 @@
+
+# relations.relation
+
+
+## RelationType Objects
+
+```python
+class RelationType(Enum)
+```
+
+Different types of relations supported by ormar:
+
+* ForeignKey = PRIMARY
+* reverse ForeignKey = REVERSE
+* ManyToMany = MULTIPLE
+
+
+#### PRIMARY
+
+
+#### REVERSE
+
+
+#### MULTIPLE
+
+
+## Relation Objects
+
+```python
+class Relation()
+```
+
+Keeps related Models and handles adding/removing of the children.
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__(manager: "RelationsManager", type_: RelationType, field_name: str, to: Type["T"], through: Type["T"] = None) -> None
+```
+
+Initialize the Relation and keep the related models either as instances of
+passed Model, or as a RelationProxy which is basically a list of models with
+some special behavior, as it exposes QuerySetProxy and allows querying the
+related models already pre filtered by parent model.
+
+**Arguments**:
+
+- `manager (RelationsManager)`: reference to relation manager
+- `type_ (RelationType)`: type of the relation
+- `field_name (str)`: name of the relation field
+- `to (Type[Model])`: model to which relation leads to
+- `through (Type[Model])`: model through which relation goes for m2m relations
+
+
+#### \_clean\_related
+
+```python
+ | _clean_related() -> None
+```
+
+Removes dead weakrefs from RelationProxy.
+
+
+#### \_find\_existing
+
+```python
+ | _find_existing(child: Union["NewBaseModel", Type["NewBaseModel"]]) -> Optional[int]
+```
+
+Find child model in RelationProxy if exists.
+
+**Arguments**:
+
+- `child (Model)`: child model to find
+
+**Returns**:
+
+`(Optional[ind])`: index of child in RelationProxy
+
+
+#### add
+
+```python
+ | add(child: "T") -> None
+```
+
+Adds child Model to relation, either sets child as related model or adds
+it to the list in RelationProxy depending on relation type.
+
+**Arguments**:
+
+- `child (Model)`: model to add to relation
+
+
+#### remove
+
+```python
+ | remove(child: Union["NewBaseModel", Type["NewBaseModel"]]) -> None
+```
+
+Removes child Model from relation, either sets None as related model or removes
+it from the list in RelationProxy depending on relation type.
+
+**Arguments**:
+
+- `child (Model)`: model to remove from relation
+
+
+#### get
+
+```python
+ | get() -> Optional[Union[List["T"], "T"]]
+```
+
+Return the related model or models from RelationProxy.
+
+**Returns**:
+
+`(Optional[Union[List[Model], Model]])`: related model/models if set
+
+
+#### \_\_repr\_\_
+
+```python
+ | __repr__() -> str
+```
+
diff --git a/docs/api/relations/utils.md b/docs/api/relations/utils.md
new file mode 100644
index 0000000..cf3c945
--- /dev/null
+++ b/docs/api/relations/utils.md
@@ -0,0 +1,26 @@
+
+# relations.utils
+
+
+#### get\_relations\_sides\_and\_names
+
+```python
+get_relations_sides_and_names(to_field: Type[BaseField], parent: "Model", child: "Model", child_name: str, virtual: bool, relation_name: str) -> Tuple["Model", "Model", str, str]
+```
+
+Determines the names of child and parent relations names, as well as
+changes one of the sides of the relation into weakref.proxy to model.
+
+**Arguments**:
+
+- `to_field (BaseField)`: field with relation definition
+- `parent (Model)`: parent model
+- `child (Model)`: child model
+- `child_name (str)`: name of the child
+- `virtual (bool)`: flag if relation is virtual
+- `relation_name ()`:
+
+**Returns**:
+
+`(Tuple["Model", "Model", str, str])`: parent, child, child_name, to_name
+
diff --git a/docs/api/signals/decorators.md b/docs/api/signals/decorators.md
new file mode 100644
index 0000000..de7fe8b
--- /dev/null
+++ b/docs/api/signals/decorators.md
@@ -0,0 +1,130 @@
+
+# decorators.signals
+
+
+#### receiver
+
+```python
+receiver(signal: str, senders: Union[Type["Model"], List[Type["Model"]]]) -> Callable
+```
+
+Connect given function to all senders for given signal name.
+
+**Arguments**:
+
+- `signal (str)`: name of the signal to register to
+- `senders (Union[Type["Model"], List[Type["Model"]]])`: one or a list of "Model" classes
+that should have the signal receiver registered
+
+**Returns**:
+
+`(Callable)`: returns the original function untouched
+
+
+#### post\_save
+
+```python
+post_save(senders: Union[Type["Model"], List[Type["Model"]]]) -> Callable
+```
+
+Connect given function to all senders for post_save signal.
+
+**Arguments**:
+
+- `senders (Union[Type["Model"], List[Type["Model"]]])`: one or a list of "Model" classes
+that should have the signal receiver registered
+
+**Returns**:
+
+`(Callable)`: returns the original function untouched
+
+
+#### post\_update
+
+```python
+post_update(senders: Union[Type["Model"], List[Type["Model"]]]) -> Callable
+```
+
+Connect given function to all senders for post_update signal.
+
+**Arguments**:
+
+- `senders (Union[Type["Model"], List[Type["Model"]]])`: one or a list of "Model" classes
+that should have the signal receiver registered
+
+**Returns**:
+
+`(Callable)`: returns the original function untouched
+
+
+#### post\_delete
+
+```python
+post_delete(senders: Union[Type["Model"], List[Type["Model"]]]) -> Callable
+```
+
+Connect given function to all senders for post_delete signal.
+
+**Arguments**:
+
+- `senders (Union[Type["Model"], List[Type["Model"]]])`: one or a list of "Model" classes
+that should have the signal receiver registered
+
+**Returns**:
+
+`(Callable)`: returns the original function untouched
+
+
+#### pre\_save
+
+```python
+pre_save(senders: Union[Type["Model"], List[Type["Model"]]]) -> Callable
+```
+
+Connect given function to all senders for pre_save signal.
+
+**Arguments**:
+
+- `senders (Union[Type["Model"], List[Type["Model"]]])`: one or a list of "Model" classes
+that should have the signal receiver registered
+
+**Returns**:
+
+`(Callable)`: returns the original function untouched
+
+
+#### pre\_update
+
+```python
+pre_update(senders: Union[Type["Model"], List[Type["Model"]]]) -> Callable
+```
+
+Connect given function to all senders for pre_update signal.
+
+**Arguments**:
+
+- `senders (Union[Type["Model"], List[Type["Model"]]])`: one or a list of "Model" classes
+that should have the signal receiver registered
+
+**Returns**:
+
+`(Callable)`: returns the original function untouched
+
+
+#### pre\_delete
+
+```python
+pre_delete(senders: Union[Type["Model"], List[Type["Model"]]]) -> Callable
+```
+
+Connect given function to all senders for pre_delete signal.
+
+**Arguments**:
+
+- `senders (Union[Type["Model"], List[Type["Model"]]])`: one or a list of "Model" classes
+that should have the signal receiver registered
+
+**Returns**:
+
+`(Callable)`: returns the original function untouched
+
diff --git a/docs/api/signals/signal.md b/docs/api/signals/signal.md
new file mode 100644
index 0000000..547ecf8
--- /dev/null
+++ b/docs/api/signals/signal.md
@@ -0,0 +1,143 @@
+
+# signals
+
+Signals and SignalEmitter that gathers the signals on models Meta.
+Used to signal receivers functions about events, i.e. post_save, pre_delete etc.
+
+
+#### \_\_all\_\_
+
+
+# signals.signal
+
+
+#### callable\_accepts\_kwargs
+
+```python
+callable_accepts_kwargs(func: Callable) -> bool
+```
+
+Checks if function accepts **kwargs.
+
+**Arguments**:
+
+- `func (function)`: function which signature needs to be checked
+
+**Returns**:
+
+`(bool)`: result of the check
+
+
+#### make\_id
+
+```python
+make_id(target: Any) -> Union[int, Tuple[int, int]]
+```
+
+Creates id of a function or method to be used as key to store signal
+
+**Arguments**:
+
+- `target (Any)`: target which id we want
+
+**Returns**:
+
+`(int)`: id of the target
+
+
+## Signal Objects
+
+```python
+class Signal()
+```
+
+Signal that notifies all receiver functions.
+In ormar used by models to send pre_save, post_save etc. signals.
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__() -> None
+```
+
+
+#### connect
+
+```python
+ | connect(receiver: Callable) -> None
+```
+
+Connects given receiver function to the signal.
+
+**Raises**:
+
+- `SignalDefinitionError`: if receiver is not callable
+or not accept **kwargs
+
+**Arguments**:
+
+- `receiver (Callable)`: receiver function
+
+
+#### disconnect
+
+```python
+ | disconnect(receiver: Callable) -> bool
+```
+
+Removes the receiver function from the signal.
+
+**Arguments**:
+
+- `receiver (Callable)`: receiver function
+
+**Returns**:
+
+`(bool)`: flag if receiver was removed
+
+
+#### send
+
+```python
+ | async send(sender: Type["Model"], **kwargs: Any) -> None
+```
+
+Notifies all receiver functions with given kwargs
+
+**Arguments**:
+
+- `sender (Type["Model"])`: model that sends the signal
+- `kwargs (Any)`: arguments passed to receivers
+
+
+## SignalEmitter Objects
+
+```python
+class SignalEmitter()
+```
+
+Emitter that registers the signals in internal dictionary.
+If signal with given name does not exist it's auto added on access.
+
+
+#### \_\_init\_\_
+
+```python
+ | __init__() -> None
+```
+
+
+#### \_\_getattr\_\_
+
+```python
+ | __getattr__(item: str) -> Signal
+```
+
+
+#### \_\_setattr\_\_
+
+```python
+ | __setattr__(key: str, value: Any) -> None
+```
+
diff --git a/docs/releases.md b/docs/releases.md
index ca9c939..580c0f1 100644
--- a/docs/releases.md
+++ b/docs/releases.md
@@ -27,6 +27,7 @@ as the same model can be registered multiple times and `ormar` needs to know fro
* Divide relations section into subsections
* Divide fields section into subsections
* Add model inheritance section
+* Add API (BETA) documentation
# 0.7.5
diff --git a/mkdocs.yml b/mkdocs.yml
index 5a48d36..126fc97 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -24,11 +24,58 @@ nav:
- PyCharm plugin: plugin.md
- Contributing: contributing.md
- Release Notes: releases.md
+ - Api (BETA):
+ - Index: api/index.md
+ - Models:
+ - Helpers:
+ - api/models/helpers/models.md
+ - api/models/helpers/pydantic.md
+ - api/models/helpers/relations.md
+ - api/models/helpers/sqlalchemy.md
+ - Mixins:
+ - Alias Mixin: api/models/mixins/alias-mixin.md
+ - Excludable Mixin: api/models/mixins/excludable-mixin.md
+ - Merge Model Mixin: api/models/mixins/merge-model-mixin.md
+ - Prefetch Query Mixin: api/models/mixins/prefetch-query-mixin.md
+ - Relation Mixin: api/models/mixins/relation-mixin.md
+ - Save Prepare Mixin: api/models/mixins/save-prepare-mixin.md
+ - api/models/model.md
+ - New BaseModel: api/models/new-basemodel.md
+ - Model Table Proxy: api/models/model-table-proxy.md
+ - Model Metaclass: api/models/model-metaclass.md
+ - Fields:
+ - Base Field: api/fields/base-field.md
+ - Model Fields: api/fields/model-fields.md
+ - Foreign Key: api/fields/foreign-key.md
+ - Many To Many: api/fields/many-to-many.md
+ - api/fields/decorators.md
+ - Query Set:
+ - Query Set: api/query-set/query-set.md
+ - api/query-set/query.md
+ - Prefetch Query: api/query-set/prefetch-query.md
+ - api/query-set/join.md
+ - api/query-set/clause.md
+ - Filter Query: api/query-set/filter-query.md
+ - Order Query: api/query-set/order-query.md
+ - Limit Query: api/query-set/limit-query.md
+ - Offset Query: api/query-set/offset-query.md
+ - api/query-set/utils.md
+ - Relations:
+ - Relation Manager: api/relations/relation-manager.md
+ - api/relations/relation.md
+ - Relation Proxy: api/relations/relation-proxy.md
+ - Queryset Proxy: api/relations/queryset-proxy.md
+ - Alias Manager: api/relations/alias-manager.md
+ - api/relations/utils.md
+ - Signals:
+ - api/signals/signal.md
+ - api/signals/decorators.md
+ - Exceptions: api/exceptions.md
repo_name: collerek/ormar
repo_url: https://github.com/collerek/ormar
-google_analytics:
- - UA-72514911-3
- - auto
+#google_analytics:
+# - UA-72514911-3
+# - auto
theme:
name: material
highlightjs: true
diff --git a/ormar/__init__.py b/ormar/__init__.py
index 044217b..88f81ba 100644
--- a/ormar/__init__.py
+++ b/ormar/__init__.py
@@ -1,3 +1,24 @@
+"""
+The `ormar` package is an async mini ORM for Python, with support for **Postgres,
+MySQL**, and **SQLite**.
+
+The main benefit of using `ormar` are:
+
+* getting an **async ORM that can be used with async frameworks**
+(fastapi, starlette etc.)
+* getting just **one model to maintain** - you don't have to maintain pydantic
+and other orm model (sqlalchemy, peewee, gino etc.)
+
+The goal was to create a simple ORM that can be **used directly
+(as request and response models)
+with `fastapi`** that bases it's data validation on pydantic.
+
+Ormar - apart form obvious ORM in name - get it's name from ormar in swedish which means
+snakes, and ormar(e) in italian which means cabinet.
+
+And what's a better name for python ORM than snakes cabinet :)
+
+"""
from ormar.decorators import (
post_delete,
post_save,
diff --git a/ormar/decorators/__init__.py b/ormar/decorators/__init__.py
index 2b5e668..69925ce 100644
--- a/ormar/decorators/__init__.py
+++ b/ormar/decorators/__init__.py
@@ -2,6 +2,7 @@
Module with all decorators that are exposed for users.
Currently only:
+
* property_field - exposing @property like function as field in Model.dict()
* predefined signals decorators (pre/post + save/update/delete)
diff --git a/ormar/decorators/property_field.py b/ormar/decorators/property_field.py
index 732cff7..69ec9da 100644
--- a/ormar/decorators/property_field.py
+++ b/ormar/decorators/property_field.py
@@ -13,7 +13,7 @@ def property_field(func: Callable) -> Union[property, Callable]:
mypy validation will complain about this.
Note that "fields" exposed like this do not go through validation.
- :raises: ModelDefinitionError if method has any other argument than self.
+ :raises ModelDefinitionError: if method has any other argument than self.
:param func: decorated function to be exposed
:type func: Callable
:return: decorated function passed in func param, with set __property_field__ = True
diff --git a/ormar/exceptions.py b/ormar/exceptions.py
index 3dbf763..cef4c83 100644
--- a/ormar/exceptions.py
+++ b/ormar/exceptions.py
@@ -1,3 +1,8 @@
+"""
+Gathers all exceptions thrown by ormar.
+"""
+
+
class AsyncOrmException(Exception):
"""
Base ormar Exception
@@ -8,7 +13,8 @@ class AsyncOrmException(Exception):
class ModelDefinitionError(AsyncOrmException):
"""
- Raised for errors related to the model definition itself.
+ Raised for errors related to the model definition itself:
+
* setting @property_field on method with arguments other than func(self)
* defining a Field without required parameters
* defining a model with more than one primary_key
@@ -46,7 +52,8 @@ class MultipleMatches(AsyncOrmException):
class QueryDefinitionError(AsyncOrmException):
"""
- Raised for errors in query definition.
+ Raised for errors in query definition:
+
* using contains or icontains filter with instance of the Model
* using Queryset.update() without filter and setting each flag to True
* using Queryset.delete() without filter and setting each flag to True
diff --git a/ormar/fields/foreign_key.py b/ormar/fields/foreign_key.py
index b920e0c..7a6bcb0 100644
--- a/ormar/fields/foreign_key.py
+++ b/ormar/fields/foreign_key.py
@@ -77,6 +77,11 @@ class UniqueColumns(UniqueConstraint):
@dataclass
class ForeignKeyConstraint:
+ """
+ Internal container to store ForeignKey definitions used later
+ to produce sqlalchemy.ForeignKeys
+ """
+
name: str
ondelete: str
onupdate: str
@@ -114,10 +119,10 @@ def ForeignKey( # noqa CFQ002
It is for reversed FK and auto generated FK on through model in Many2Many relations.
:type virtual: bool
:param onupdate: parameter passed to sqlalchemy.ForeignKey.
- How to treat child rows on update of parent (the one wher FK is defined) model.
+ How to treat child rows on update of parent (the one where FK is defined) model.
:type onupdate: str
:param ondelete: parameter passed to sqlalchemy.ForeignKey.
- How to treat child rows on delete of parent (the one wher FK is defined) model.
+ How to treat child rows on delete of parent (the one where FK is defined) model.
:type ondelete: str
:param kwargs: all other args to be populated by BaseField
:type kwargs: Any
diff --git a/ormar/fields/model_fields.py b/ormar/fields/model_fields.py
index ef35030..4a30ee3 100644
--- a/ormar/fields/model_fields.py
+++ b/ormar/fields/model_fields.py
@@ -116,6 +116,10 @@ class ModelFieldFactory:
class String(ModelFieldFactory, str):
+ """
+ String field factory that construct Field classes and populated their values.
+ """
+
_type = str
def __new__( # type: ignore # noqa CFQ002
@@ -142,10 +146,24 @@ class String(ModelFieldFactory, str):
@classmethod
def get_column_type(cls, **kwargs: Any) -> Any:
+ """
+ Return proper type of db column for given field type.
+ Accepts required and optional parameters that each column type accepts.
+
+ :param kwargs: key, value pairs of sqlalchemy options
+ :type kwargs: Any
+ :return: initialized column with proper options
+ :rtype: sqlalchemy Column
+ """
return sqlalchemy.String(length=kwargs.get("max_length"))
@classmethod
def validate(cls, **kwargs: Any) -> None:
+ """
+ Used to validate if all required parameters on a given field type are set.
+ :param kwargs: all params passed during construction
+ :type kwargs: Any
+ """
max_length = kwargs.get("max_length", None)
if max_length is None or max_length <= 0:
raise ModelDefinitionError(
@@ -154,6 +172,10 @@ class String(ModelFieldFactory, str):
class Integer(ModelFieldFactory, int):
+ """
+ Integer field factory that construct Field classes and populated their values.
+ """
+
_type = int
def __new__( # type: ignore
@@ -184,10 +206,23 @@ class Integer(ModelFieldFactory, int):
@classmethod
def get_column_type(cls, **kwargs: Any) -> Any:
+ """
+ Return proper type of db column for given field type.
+ Accepts required and optional parameters that each column type accepts.
+
+ :param kwargs: key, value pairs of sqlalchemy options
+ :type kwargs: Any
+ :return: initialized column with proper options
+ :rtype: sqlalchemy Column
+ """
return sqlalchemy.Integer()
class Text(ModelFieldFactory, str):
+ """
+ Text field factory that construct Field classes and populated their values.
+ """
+
_type = str
def __new__( # type: ignore
@@ -206,10 +241,23 @@ class Text(ModelFieldFactory, str):
@classmethod
def get_column_type(cls, **kwargs: Any) -> Any:
+ """
+ Return proper type of db column for given field type.
+ Accepts required and optional parameters that each column type accepts.
+
+ :param kwargs: key, value pairs of sqlalchemy options
+ :type kwargs: Any
+ :return: initialized column with proper options
+ :rtype: sqlalchemy Column
+ """
return sqlalchemy.Text()
class Float(ModelFieldFactory, float):
+ """
+ Float field factory that construct Field classes and populated their values.
+ """
+
_type = float
def __new__( # type: ignore
@@ -234,6 +282,15 @@ class Float(ModelFieldFactory, float):
@classmethod
def get_column_type(cls, **kwargs: Any) -> Any:
+ """
+ Return proper type of db column for given field type.
+ Accepts required and optional parameters that each column type accepts.
+
+ :param kwargs: key, value pairs of sqlalchemy options
+ :type kwargs: Any
+ :return: initialized column with proper options
+ :rtype: sqlalchemy Column
+ """
return sqlalchemy.Float()
@@ -246,46 +303,115 @@ if TYPE_CHECKING: # pragma: nocover
else:
class Boolean(ModelFieldFactory, int):
+ """
+ Boolean field factory that construct Field classes and populated their values.
+ """
+
_type = bool
@classmethod
def get_column_type(cls, **kwargs: Any) -> Any:
+ """
+ Return proper type of db column for given field type.
+ Accepts required and optional parameters that each column type accepts.
+
+ :param kwargs: key, value pairs of sqlalchemy options
+ :type kwargs: Any
+ :return: initialized column with proper options
+ :rtype: sqlalchemy Column
+ """
return sqlalchemy.Boolean()
class DateTime(ModelFieldFactory, datetime.datetime):
+ """
+ DateTime field factory that construct Field classes and populated their values.
+ """
+
_type = datetime.datetime
@classmethod
def get_column_type(cls, **kwargs: Any) -> Any:
+ """
+ Return proper type of db column for given field type.
+ Accepts required and optional parameters that each column type accepts.
+
+ :param kwargs: key, value pairs of sqlalchemy options
+ :type kwargs: Any
+ :return: initialized column with proper options
+ :rtype: sqlalchemy Column
+ """
return sqlalchemy.DateTime()
class Date(ModelFieldFactory, datetime.date):
+ """
+ Date field factory that construct Field classes and populated their values.
+ """
+
_type = datetime.date
@classmethod
def get_column_type(cls, **kwargs: Any) -> Any:
+ """
+ Return proper type of db column for given field type.
+ Accepts required and optional parameters that each column type accepts.
+
+ :param kwargs: key, value pairs of sqlalchemy options
+ :type kwargs: Any
+ :return: initialized column with proper options
+ :rtype: sqlalchemy Column
+ """
return sqlalchemy.Date()
class Time(ModelFieldFactory, datetime.time):
+ """
+ Time field factory that construct Field classes and populated their values.
+ """
+
_type = datetime.time
@classmethod
def get_column_type(cls, **kwargs: Any) -> Any:
+ """
+ Return proper type of db column for given field type.
+ Accepts required and optional parameters that each column type accepts.
+
+ :param kwargs: key, value pairs of sqlalchemy options
+ :type kwargs: Any
+ :return: initialized column with proper options
+ :rtype: sqlalchemy Column
+ """
return sqlalchemy.Time()
class JSON(ModelFieldFactory, pydantic.Json):
+ """
+ JSON field factory that construct Field classes and populated their values.
+ """
+
_type = pydantic.Json
@classmethod
def get_column_type(cls, **kwargs: Any) -> Any:
+ """
+ Return proper type of db column for given field type.
+ Accepts required and optional parameters that each column type accepts.
+
+ :param kwargs: key, value pairs of sqlalchemy options
+ :type kwargs: Any
+ :return: initialized column with proper options
+ :rtype: sqlalchemy Column
+ """
return sqlalchemy.JSON()
class BigInteger(Integer, int):
+ """
+ BigInteger field factory that construct Field classes and populated their values.
+ """
+
_type = int
def __new__( # type: ignore
@@ -316,10 +442,23 @@ class BigInteger(Integer, int):
@classmethod
def get_column_type(cls, **kwargs: Any) -> Any:
+ """
+ Return proper type of db column for given field type.
+ Accepts required and optional parameters that each column type accepts.
+
+ :param kwargs: key, value pairs of sqlalchemy options
+ :type kwargs: Any
+ :return: initialized column with proper options
+ :rtype: sqlalchemy Column
+ """
return sqlalchemy.BigInteger()
class Decimal(ModelFieldFactory, decimal.Decimal):
+ """
+ Decimal field factory that construct Field classes and populated their values.
+ """
+
_type = decimal.Decimal
def __new__( # type: ignore # noqa CFQ002
@@ -359,12 +498,26 @@ class Decimal(ModelFieldFactory, decimal.Decimal):
@classmethod
def get_column_type(cls, **kwargs: Any) -> Any:
+ """
+ Return proper type of db column for given field type.
+ Accepts required and optional parameters that each column type accepts.
+
+ :param kwargs: key, value pairs of sqlalchemy options
+ :type kwargs: Any
+ :return: initialized column with proper options
+ :rtype: sqlalchemy Column
+ """
precision = kwargs.get("precision")
scale = kwargs.get("scale")
return sqlalchemy.DECIMAL(precision=precision, scale=scale)
@classmethod
def validate(cls, **kwargs: Any) -> None:
+ """
+ Used to validate if all required parameters on a given field type are set.
+ :param kwargs: all params passed during construction
+ :type kwargs: Any
+ """
precision = kwargs.get("precision")
scale = kwargs.get("scale")
if precision is None or precision < 0 or scale is None or scale < 0:
@@ -374,6 +527,10 @@ class Decimal(ModelFieldFactory, decimal.Decimal):
class UUID(ModelFieldFactory, uuid.UUID):
+ """
+ UUID field factory that construct Field classes and populated their values.
+ """
+
_type = uuid.UUID
def __new__( # type: ignore # noqa CFQ002
@@ -392,5 +549,14 @@ class UUID(ModelFieldFactory, uuid.UUID):
@classmethod
def get_column_type(cls, **kwargs: Any) -> Any:
+ """
+ Return proper type of db column for given field type.
+ Accepts required and optional parameters that each column type accepts.
+
+ :param kwargs: key, value pairs of sqlalchemy options
+ :type kwargs: Any
+ :return: initialized column with proper options
+ :rtype: sqlalchemy Column
+ """
uuid_format = kwargs.get("uuid_format", "hex")
return sqlalchemy_uuid.UUID(uuid_format=uuid_format)
diff --git a/ormar/models/__init__.py b/ormar/models/__init__.py
index 9e366f1..88a39c6 100644
--- a/ormar/models/__init__.py
+++ b/ormar/models/__init__.py
@@ -1,3 +1,9 @@
+"""
+Definition of Model, it's parents NewBaseModel and mixins used by models.
+Also defines a Metaclass that handles all constructions and relations registration,
+ass well as vast number of helper functions for pydantic, sqlalchemy and relations.
+"""
+
from ormar.models.newbasemodel import NewBaseModel # noqa I100
from ormar.models.model import Model # noqa I100
diff --git a/ormar/models/helpers/models.py b/ormar/models/helpers/models.py
index 4b5a364..61da7bb 100644
--- a/ormar/models/helpers/models.py
+++ b/ormar/models/helpers/models.py
@@ -61,7 +61,7 @@ def validate_related_names_in_relations(
(populated by default as model.name.lower()+'s').
Also related_names have to be unique for given related model.
- :raises: ModelDefinitionError if validation of related_names fail
+ :raises ModelDefinitionError: if validation of related_names fail
:param model_fields: dictionary of declared ormar model fields
:type model_fields: Dict[str, ormar.Field]
:param new_model:
diff --git a/ormar/models/helpers/relations.py b/ormar/models/helpers/relations.py
index c9f8f48..4792531 100644
--- a/ormar/models/helpers/relations.py
+++ b/ormar/models/helpers/relations.py
@@ -157,7 +157,7 @@ def verify_related_name_dont_duplicate(
auto generated) is already used on related model, but is connected with other model
than the one that we connect right now.
- :raises: ModelDefinitionError if name is already used but lead to different related
+ :raises ModelDefinitionError: if name is already used but lead to different related
model
:param child: related Model class
:type child: ormar.models.metaclass.ModelMetaclass
@@ -191,7 +191,7 @@ def reverse_field_not_already_registered(
"""
Checks if child is already registered in parents pydantic fields.
- :raises: ModelDefinitionError if related name is already used but lead to different
+ :raises ModelDefinitionError: if related name is already used but lead to different
related model
:param child: related Model class
:type child: ormar.models.metaclass.ModelMetaclass
diff --git a/ormar/models/helpers/sqlalchemy.py b/ormar/models/helpers/sqlalchemy.py
index 723cb54..37cdaa9 100644
--- a/ormar/models/helpers/sqlalchemy.py
+++ b/ormar/models/helpers/sqlalchemy.py
@@ -84,7 +84,7 @@ def check_pk_column_validity(
was not already set (only one allowed per model) and if field is not marked
as pydantic_only as it needs to be a database field.
- :raises: ModelDefintionError if pkname already set or field is pydantic_only
+ :raises ModelDefintionError: if pkname already set or field is pydantic_only
:param field_name: name of field
:type field_name: str
:param field: ormar.Field
@@ -121,7 +121,7 @@ def sqlalchemy_columns_from_model_fields(
Append fields to columns if it's not pydantic_only,
virtual ForeignKey or ManyToMany field.
- :raises: ModelDefinitionError if validation of related_names fail,
+ :raises ModelDefinitionError: if validation of related_names fail,
or pkname validation fails.
:param model_fields: dictionary of declared ormar model fields
:type model_fields: Dict[str, ormar.Field]
@@ -162,7 +162,7 @@ def populate_meta_tablename_columns_and_pk(
If not calls the sqlalchemy_columns_from_model_fields to populate
columns from ormar.fields definitions.
- :raises: if pkname is not present raises ModelDefinitionError.
+ :raises ModelDefinitionError: if pkname is not present raises ModelDefinitionError.
Each model has to have pk.
:param name: name of the current Model
diff --git a/ormar/models/metaclass.py b/ormar/models/metaclass.py
index 9d438d5..17e844d 100644
--- a/ormar/models/metaclass.py
+++ b/ormar/models/metaclass.py
@@ -48,7 +48,7 @@ CONFIG_KEY = "Config"
class ModelMeta:
"""
Class used for type hinting.
- Users can subclass this one for conveniance but it's not required.
+ Users can subclass this one for convenience but it's not required.
The only requirement is that ormar.Model has to have inner class with name Meta.
"""
@@ -86,7 +86,7 @@ def choices_validator(cls: Type["Model"], values: Dict[str, Any]) -> Dict[str, A
Validator that is attached to pydantic model pre root validators.
Validator checks if field value is in field.choices list.
- :raises: ValueError if field value is outside of allowed choices.
+ :raises ValueError: if field value is outside of allowed choices.
:param cls: constructed class
:type cls: Model class
:param values: dictionary of field values (pydantic side)
@@ -321,7 +321,7 @@ def copy_data_from_parent_model( # noqa: CCR001
Since relation fields requires different related_name for different children
- :raises: ModelDefinitionError if non abstract model is subclassed
+ :raises ModelDefinitionError: if non abstract model is subclassed
:param base_class: one of the parent classes
:type base_class: Model or model parent class
:param curr_class: current constructed class
@@ -500,6 +500,7 @@ class ModelMetaclass(pydantic.main.ModelMetaclass):
Construct parent pydantic Metaclass/ Model.
If class has Meta class declared (so actual ormar Models) it also:
+
* populate sqlalchemy columns, pkname and tables from model_fields
* register reverse relationships on related models
* registers all relations in alias manager that populates table_prefixes
diff --git a/ormar/models/mixins/save_mixin.py b/ormar/models/mixins/save_mixin.py
index 0450683..0e0884f 100644
--- a/ormar/models/mixins/save_mixin.py
+++ b/ormar/models/mixins/save_mixin.py
@@ -12,7 +12,7 @@ class SavePrepareMixin(RelationMixin, AliasMixin):
"""
@classmethod
- def _prepare_model_to_save(cls, new_kwargs: dict) -> dict:
+ def prepare_model_to_save(cls, new_kwargs: dict) -> dict:
"""
Combines all preparation methods before saving.
Removes primary key for if it's nullable or autoincrement pk field,
diff --git a/ormar/models/model.py b/ormar/models/model.py
index 9412a26..63388cb 100644
--- a/ormar/models/model.py
+++ b/ormar/models/model.py
@@ -456,7 +456,7 @@ class Model(NewBaseModel):
Sets model save status to True.
- :raises: If the pk column is not set will throw ModelPersistenceError
+ :raises ModelPersistenceError: If the pk column is not set
:param kwargs: list of fields to update as field=value pairs
:type kwargs: Any
@@ -512,7 +512,7 @@ class Model(NewBaseModel):
Be careful as the related models can be overwritten by pk_only models in load.
Does NOT refresh the related models fields if they were loaded before.
- :raises: If given pk is not found in database the NoMatch exception is raised.
+ :raises NoMatch: If given pk is not found in database.
:return: reloaded Model
:rtype: Model
diff --git a/ormar/models/newbasemodel.py b/ormar/models/newbasemodel.py
index dc0026c..6a3ea7a 100644
--- a/ormar/models/newbasemodel.py
+++ b/ormar/models/newbasemodel.py
@@ -103,7 +103,7 @@ class NewBaseModel(pydantic.BaseModel, ModelTableProxy, metaclass=ModelMetaclass
should be explicitly set to None, as otherwise pydantic will try to populate
them with their default values if default is set.
- :raises: ModelError if abstract model is initialized or unknown field is passed
+ :raises ModelError: if abstract model is initialized or unknown field is passed
:param args: ignored args
:type args: Any
:param kwargs: keyword arguments - all fields values and some special params
diff --git a/ormar/queryset/clause.py b/ormar/queryset/clause.py
index d0963cf..4746db4 100644
--- a/ormar/queryset/clause.py
+++ b/ormar/queryset/clause.py
@@ -245,7 +245,7 @@ class QueryClause:
Escapes the special characters ["%", "_"] if needed.
Adds `%` for `like` queries.
- :raises: QueryDefinitionError if contains or icontains is used with
+ :raises QueryDefinitionError: if contains or icontains is used with
ormar model instance
:param op: operator used in query
:type op: str
diff --git a/ormar/queryset/queryset.py b/ormar/queryset/queryset.py
index ffa31cc..599f4f0 100644
--- a/ormar/queryset/queryset.py
+++ b/ormar/queryset/queryset.py
@@ -647,8 +647,8 @@ class QuerySet:
"""
Gets the first row from the db ordered by primary key column ascending.
- :raises: NoMatch if no rows are returned
- :raises: MultipleMatches if more than 1 row is returned.
+ :raises NoMatch: if no rows are returned
+ :raises MultipleMatches: if more than 1 row is returned.
:param kwargs: fields names and proper value types
:type kwargs: Any
:return: returned model
@@ -675,8 +675,8 @@ class QuerySet:
Passing a criteria is actually calling filter(**kwargs) method described below.
- :raises: NoMatch if no rows are returned
- :raises: MultipleMatches if more than 1 row is returned.
+ :raises NoMatch: if no rows are returned
+ :raises MultipleMatches: if more than 1 row is returned.
:param kwargs: fields names and proper value types
:type kwargs: Any
:return: returned model
@@ -771,7 +771,7 @@ class QuerySet:
:rtype: Model
"""
new_kwargs = dict(**kwargs)
- new_kwargs = self.model._prepare_model_to_save(new_kwargs)
+ new_kwargs = self.model.prepare_model_to_save(new_kwargs)
expr = self.table.insert()
expr = expr.values(**new_kwargs)
@@ -817,7 +817,7 @@ class QuerySet:
ready_objects = []
for objt in objects:
new_kwargs = objt.dict()
- new_kwargs = objt._prepare_model_to_save(new_kwargs)
+ new_kwargs = objt.prepare_model_to_save(new_kwargs)
ready_objects.append(new_kwargs)
expr = self.table.insert()
diff --git a/ormar/queryset/utils.py b/ormar/queryset/utils.py
index 4c82310..12a7fa5 100644
--- a/ormar/queryset/utils.py
+++ b/ormar/queryset/utils.py
@@ -88,7 +88,7 @@ def convert_set_to_required_dict(set_to_convert: set) -> Dict:
:param set_to_convert: set to convert to dict
:type set_to_convert: set
:return: set converted to dict of ellipsis
- :rtype: Dict[str, ellipsis]
+ :rtype: Dict
"""
new_dict = dict()
for key in set_to_convert:
diff --git a/ormar/relations/querysetproxy.py b/ormar/relations/querysetproxy.py
index 1356a3a..386ac63 100644
--- a/ormar/relations/querysetproxy.py
+++ b/ormar/relations/querysetproxy.py
@@ -211,8 +211,8 @@ class QuerysetProxy(ormar.QuerySetProtocol):
List of related models is cleared before the call.
- :raises: NoMatch if no rows are returned
- :raises: MultipleMatches if more than 1 row is returned.
+ :raises NoMatch: if no rows are returned
+ :raises MultipleMatches: if more than 1 row is returned.
:param kwargs: fields names and proper value types
:type kwargs: Any
:return: returned model
diff --git a/ormar/relations/relation.py b/ormar/relations/relation.py
index cb4561f..d037d4a 100644
--- a/ormar/relations/relation.py
+++ b/ormar/relations/relation.py
@@ -16,10 +16,11 @@ if TYPE_CHECKING: # pragma no cover
class RelationType(Enum):
"""
- Different types of relations supported by ormar.
- ForeignKey = PRIMARY
- reverse ForeignKey = REVERSE
- ManyToMany = MULTIPLE
+ Different types of relations supported by ormar:
+
+ * ForeignKey = PRIMARY
+ * reverse ForeignKey = REVERSE
+ * ManyToMany = MULTIPLE
"""
PRIMARY = 1
diff --git a/ormar/signals/__init__.py b/ormar/signals/__init__.py
index 6f4706e..127fc2f 100644
--- a/ormar/signals/__init__.py
+++ b/ormar/signals/__init__.py
@@ -1,3 +1,7 @@
+"""
+Signals and SignalEmitter that gathers the signals on models Meta.
+Used to signal receivers functions about events, i.e. post_save, pre_delete etc.
+"""
from ormar.signals.signal import Signal, SignalEmitter
__all__ = ["Signal", "SignalEmitter"]
diff --git a/ormar/signals/signal.py b/ormar/signals/signal.py
index 0dfff24..e2c5275 100644
--- a/ormar/signals/signal.py
+++ b/ormar/signals/signal.py
@@ -14,7 +14,7 @@ def callable_accepts_kwargs(func: Callable) -> bool:
:param func: function which signature needs to be checked
:type func: function
- :return:
+ :return: result of the check
:rtype: bool
"""
return any(
@@ -51,7 +51,7 @@ class Signal:
"""
Connects given receiver function to the signal.
- :raises: SignalDefinitionError if receiver is not callable
+ :raises SignalDefinitionError: if receiver is not callable
or not accept **kwargs
:param receiver: receiver function
:type receiver: Callable
diff --git a/pydoc-markdown.yml b/pydoc-markdown.yml
new file mode 100644
index 0000000..36dea6e
--- /dev/null
+++ b/pydoc-markdown.yml
@@ -0,0 +1,152 @@
+output_directory: docs/api
+loaders:
+ - type: python
+ search_path: [ormar/]
+processors:
+ - type: filter
+ documented_only: false
+ skip_empty_modules: false
+ exclude_private: false
+ exclude_special: false
+ - type: sphinx
+ - type: crossref
+renderer:
+ type: mkdocs
+ pages:
+ - title: Models
+ children:
+ - title: Model Metaclass
+ contents:
+ - models.metaclass.*
+ - title: Model
+ contents:
+ - models.model.*
+ - title: New BaseModel
+ contents:
+ - models.newbasemodel.*
+ - title: Model Table Proxy
+ contents:
+ - models.modelproxy.*
+ - title: Helpers
+ children:
+ - title: models
+ contents:
+ - models.helpers.models.*
+ - title: pydantic
+ contents:
+ - models.helpers.pydantic.*
+ - title: relations
+ contents:
+ - models.helpers.relations.*
+ - title: sqlalchemy
+ contents:
+ - models.helpers.sqlalchemy.*
+ - title: Mixins
+ children:
+ - title: Alias Mixin
+ contents:
+ - models.mixins.alias_mixin.*
+ - title: Excludable Mixin
+ contents:
+ - models.mixins.excludable_mixin.*
+ - title: Merge Model Mixin
+ contents:
+ - models.mixins.merge_mixin.*
+ - title: Prefetch Query Mixin
+ contents:
+ - models.mixins.prefetch_mixin.*
+ - title: Relation Mixin
+ contents:
+ - models.mixins.relation_mixin.*
+ - title: Save Prepare Mixin
+ contents:
+ - models.mixins.save_mixin.*
+ - title: Fields
+ children:
+ - title: Base Field
+ contents:
+ - fields.base.*
+ - title: Model Fields
+ contents:
+ - fields.model_fields.*
+ - title: Foreign Key
+ contents:
+ - fields.foreign_key.*
+ - title: Many To Many
+ contents:
+ - fields.many_to_many.*
+ - title: Decorators
+ contents:
+ - decorators.property_field.*
+ - title: Query Set
+ children:
+ - title: Query Set
+ contents:
+ - queryset.queryset.*
+ - title: Query
+ contents:
+ - queryset.query.*
+ - title: Prefetch Query
+ contents:
+ - queryset.prefetch_query.*
+ - title: Join
+ contents:
+ - queryset.join.*
+ - title: Clause
+ contents:
+ - queryset.clause.*
+ - title: Filter Query
+ contents:
+ - queryset.filter_query.*
+ - title: Order Query
+ contents:
+ - queryset.order_query.*
+ - title: Limit Query
+ contents:
+ - queryset.limit_query.*
+ - title: Offset Query
+ contents:
+ - queryset.offset_query.*
+ - title: Utils
+ contents:
+ - queryset.utils.*
+ - title: Relations
+ children:
+ - title: Relation Manager
+ contents:
+ - relations.relation_manager.*
+ - title: Relation
+ contents:
+ - relations.relation.*
+ - title: Relation Proxy
+ contents:
+ - relations.relation_proxy.*
+ - title: Queryset Proxy
+ contents:
+ - relations.querysetproxy.*
+ - title: Alias Manager
+ contents:
+ - relations.alias_manager.*
+ - title: Utils
+ contents:
+ - relations.utils.*
+ - title: Signals
+ children:
+ - title: Signal
+ contents:
+ - signals.*
+ - title: Decorators
+ contents:
+ - decorators.signals.*
+ - title: Exceptions
+ contents:
+ - exceptions.*
+ mkdocs_config:
+ site_name: Ormar
+ theme:
+ name: material
+ highlightjs: true
+ hljs_languages:
+ - python
+ palette:
+ primary: indigo
diff --git a/requirements.txt b/requirements.txt
index 1e8b113..f47a05d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -36,5 +36,11 @@ flake8-cognitive-complexity
flake8-functions
flake8-expression-complexity
+# Documantation
+mkdocs
+mkdocs-material
+mkdocs-material-extensions
+pydoc-markdown
+
# Performance testing
yappi