next part of the docs and api documentation in beta ver

This commit is contained in:
collerek
2021-01-04 19:38:21 +01:00
parent eec17e2f78
commit 9f8e8e87e8
64 changed files with 7414 additions and 37 deletions

96
docs/api/exceptions.md Normal file
View File

@ -0,0 +1,96 @@
<a name="exceptions"></a>
# exceptions
Gathers all exceptions thrown by ormar.
<a name="exceptions.AsyncOrmException"></a>
## AsyncOrmException Objects
```python
class AsyncOrmException(Exception)
```
Base ormar Exception
<a name="exceptions.ModelDefinitionError"></a>
## 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
<a name="exceptions.ModelError"></a>
## ModelError Objects
```python
class ModelError(AsyncOrmException)
```
Raised for initialization of model with non-existing field keyword.
<a name="exceptions.NoMatch"></a>
## NoMatch Objects
```python
class NoMatch(AsyncOrmException)
```
Raised for database queries that has no matching result (empty result).
<a name="exceptions.MultipleMatches"></a>
## 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.
<a name="exceptions.QueryDefinitionError"></a>
## 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
<a name="exceptions.RelationshipInstanceError"></a>
## RelationshipInstanceError Objects
```python
class RelationshipInstanceError(AsyncOrmException)
```
<a name="exceptions.ModelPersistenceError"></a>
## 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).
<a name="exceptions.SignalDefinitionError"></a>
## SignalDefinitionError Objects
```python
class SignalDefinitionError(AsyncOrmException)
```
Raised when non callable receiver is passed as signal callback.

View File

@ -0,0 +1,292 @@
<a name="fields.base"></a>
# fields.base
<a name="fields.base.BaseField"></a>
## 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
<a name="fields.base.BaseField.__type__"></a>
#### \_\_type\_\_
<a name="fields.base.BaseField.related_name"></a>
#### related\_name
<a name="fields.base.BaseField.column_type"></a>
#### column\_type
<a name="fields.base.BaseField.constraints"></a>
#### constraints
<a name="fields.base.BaseField.name"></a>
#### name
<a name="fields.base.BaseField.alias"></a>
#### alias
<a name="fields.base.BaseField.primary_key"></a>
#### primary\_key
<a name="fields.base.BaseField.autoincrement"></a>
#### autoincrement
<a name="fields.base.BaseField.nullable"></a>
#### nullable
<a name="fields.base.BaseField.index"></a>
#### index
<a name="fields.base.BaseField.unique"></a>
#### unique
<a name="fields.base.BaseField.pydantic_only"></a>
#### pydantic\_only
<a name="fields.base.BaseField.virtual"></a>
#### virtual
<a name="fields.base.BaseField.choices"></a>
#### choices
<a name="fields.base.BaseField.to"></a>
#### to
<a name="fields.base.BaseField.through"></a>
#### through
<a name="fields.base.BaseField.default"></a>
#### default
<a name="fields.base.BaseField.server_default"></a>
#### server\_default
<a name="fields.base.BaseField.is_valid_uni_relation"></a>
#### 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
<a name="fields.base.BaseField.get_alias"></a>
#### 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
<a name="fields.base.BaseField.is_valid_field_info_field"></a>
#### 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
<a name="fields.base.BaseField.convert_to_pydantic_field_info"></a>
#### 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
<a name="fields.base.BaseField.default_value"></a>
#### 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
<a name="fields.base.BaseField.get_default"></a>
#### 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
<a name="fields.base.BaseField.has_default"></a>
#### 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
<a name="fields.base.BaseField.is_auto_primary_key"></a>
#### 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
<a name="fields.base.BaseField.construct_constraints"></a>
#### 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.
<a name="fields.base.BaseField.get_column"></a>
#### 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.
<a name="fields.base.BaseField.expand_relationship"></a>
#### 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

View File

@ -0,0 +1,28 @@
<a name="decorators.property_field"></a>
# decorators.property\_field
<a name="decorators.property_field.property_field"></a>
#### 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

View File

@ -0,0 +1,267 @@
<a name="fields.foreign_key"></a>
# fields.foreign\_key
<a name="fields.foreign_key.create_dummy_instance"></a>
#### 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
<a name="fields.foreign_key.create_dummy_model"></a>
#### 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
<a name="fields.foreign_key.UniqueColumns"></a>
## UniqueColumns Objects
```python
class UniqueColumns(UniqueConstraint)
```
Subclass of sqlalchemy.UniqueConstraint.
Used to avoid importing anything from sqlalchemy by user.
<a name="fields.foreign_key.ForeignKeyConstraint"></a>
## ForeignKeyConstraint Objects
```python
@dataclass
class ForeignKeyConstraint()
```
Internal container to store ForeignKey definitions used later
to produce sqlalchemy.ForeignKeys
<a name="fields.foreign_key.ForeignKeyConstraint.name"></a>
#### name
<a name="fields.foreign_key.ForeignKeyConstraint.ondelete"></a>
#### ondelete
<a name="fields.foreign_key.ForeignKeyConstraint.onupdate"></a>
#### onupdate
<a name="fields.foreign_key.ForeignKey"></a>
#### 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
<a name="fields.foreign_key.ForeignKeyField"></a>
## ForeignKeyField Objects
```python
class ForeignKeyField(BaseField)
```
Actual class returned from ForeignKey function call and stored in model_fields.
<a name="fields.foreign_key.ForeignKeyField.to"></a>
#### to
<a name="fields.foreign_key.ForeignKeyField.name"></a>
#### name
<a name="fields.foreign_key.ForeignKeyField.related_name"></a>
#### related\_name
<a name="fields.foreign_key.ForeignKeyField.virtual"></a>
#### virtual
<a name="fields.foreign_key.ForeignKeyField._extract_model_from_sequence"></a>
#### \_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
<a name="fields.foreign_key.ForeignKeyField._register_existing_model"></a>
#### \_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
<a name="fields.foreign_key.ForeignKeyField._construct_model_from_dict"></a>
#### \_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
<a name="fields.foreign_key.ForeignKeyField._construct_model_from_pk"></a>
#### \_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
<a name="fields.foreign_key.ForeignKeyField.register_relation"></a>
#### 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
<a name="fields.foreign_key.ForeignKeyField.expand_relationship"></a>
#### 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

View File

@ -0,0 +1,59 @@
<a name="fields.many_to_many"></a>
# fields.many\_to\_many
<a name="fields.many_to_many.REF_PREFIX"></a>
#### REF\_PREFIX
<a name="fields.many_to_many.ManyToMany"></a>
#### 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
<a name="fields.many_to_many.ManyToManyField"></a>
## ManyToManyField Objects
```python
class ManyToManyField(ForeignKeyField, ormar.QuerySetProtocol, ormar.RelationProtocol)
```
Actual class returned from ManyToMany function call and stored in model_fields.
<a name="fields.many_to_many.ManyToManyField.through"></a>
#### through
<a name="fields.many_to_many.ManyToManyField.default_target_field_name"></a>
#### 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

View File

@ -0,0 +1,514 @@
<a name="fields.model_fields"></a>
# fields.model\_fields
<a name="fields.model_fields.is_field_nullable"></a>
#### 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
<a name="fields.model_fields.is_auto_primary_key"></a>
#### 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
<a name="fields.model_fields.ModelFieldFactory"></a>
## ModelFieldFactory Objects
```python
class ModelFieldFactory()
```
Default field factory that construct Field classes and populated their values.
<a name="fields.model_fields.ModelFieldFactory._bases"></a>
#### \_bases
<a name="fields.model_fields.ModelFieldFactory._type"></a>
#### \_type
<a name="fields.model_fields.ModelFieldFactory.__new__"></a>
#### \_\_new\_\_
```python
| __new__(cls, *args: Any, **kwargs: Any) -> Type[BaseField]
```
<a name="fields.model_fields.ModelFieldFactory.get_column_type"></a>
#### 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
<a name="fields.model_fields.ModelFieldFactory.validate"></a>
#### 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
<a name="fields.model_fields.String"></a>
## String Objects
```python
class String(ModelFieldFactory, str)
```
String field factory that construct Field classes and populated their values.
<a name="fields.model_fields.String._type"></a>
#### \_type
<a name="fields.model_fields.String.__new__"></a>
#### \_\_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]
```
<a name="fields.model_fields.String.get_column_type"></a>
#### 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
<a name="fields.model_fields.String.validate"></a>
#### 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
<a name="fields.model_fields.Integer"></a>
## Integer Objects
```python
class Integer(ModelFieldFactory, int)
```
Integer field factory that construct Field classes and populated their values.
<a name="fields.model_fields.Integer._type"></a>
#### \_type
<a name="fields.model_fields.Integer.__new__"></a>
#### \_\_new\_\_
```python
| __new__(cls, *, minimum: int = None, maximum: int = None, multiple_of: int = None, **kwargs: Any) -> Type[BaseField]
```
<a name="fields.model_fields.Integer.get_column_type"></a>
#### 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
<a name="fields.model_fields.Text"></a>
## Text Objects
```python
class Text(ModelFieldFactory, str)
```
Text field factory that construct Field classes and populated their values.
<a name="fields.model_fields.Text._type"></a>
#### \_type
<a name="fields.model_fields.Text.__new__"></a>
#### \_\_new\_\_
```python
| __new__(cls, *, allow_blank: bool = True, strip_whitespace: bool = False, **kwargs: Any) -> Type[BaseField]
```
<a name="fields.model_fields.Text.get_column_type"></a>
#### 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
<a name="fields.model_fields.Float"></a>
## Float Objects
```python
class Float(ModelFieldFactory, float)
```
Float field factory that construct Field classes and populated their values.
<a name="fields.model_fields.Float._type"></a>
#### \_type
<a name="fields.model_fields.Float.__new__"></a>
#### \_\_new\_\_
```python
| __new__(cls, *, minimum: float = None, maximum: float = None, multiple_of: int = None, **kwargs: Any) -> Type[BaseField]
```
<a name="fields.model_fields.Float.get_column_type"></a>
#### 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
<a name="fields.model_fields.DateTime"></a>
## DateTime Objects
```python
class DateTime(ModelFieldFactory, datetime.datetime)
```
DateTime field factory that construct Field classes and populated their values.
<a name="fields.model_fields.DateTime._type"></a>
#### \_type
<a name="fields.model_fields.DateTime.get_column_type"></a>
#### 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
<a name="fields.model_fields.Date"></a>
## Date Objects
```python
class Date(ModelFieldFactory, datetime.date)
```
Date field factory that construct Field classes and populated their values.
<a name="fields.model_fields.Date._type"></a>
#### \_type
<a name="fields.model_fields.Date.get_column_type"></a>
#### 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
<a name="fields.model_fields.Time"></a>
## Time Objects
```python
class Time(ModelFieldFactory, datetime.time)
```
Time field factory that construct Field classes and populated their values.
<a name="fields.model_fields.Time._type"></a>
#### \_type
<a name="fields.model_fields.Time.get_column_type"></a>
#### 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
<a name="fields.model_fields.JSON"></a>
## JSON Objects
```python
class JSON(ModelFieldFactory, pydantic.Json)
```
JSON field factory that construct Field classes and populated their values.
<a name="fields.model_fields.JSON._type"></a>
#### \_type
<a name="fields.model_fields.JSON.get_column_type"></a>
#### 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
<a name="fields.model_fields.BigInteger"></a>
## BigInteger Objects
```python
class BigInteger(Integer, int)
```
BigInteger field factory that construct Field classes and populated their values.
<a name="fields.model_fields.BigInteger._type"></a>
#### \_type
<a name="fields.model_fields.BigInteger.__new__"></a>
#### \_\_new\_\_
```python
| __new__(cls, *, minimum: int = None, maximum: int = None, multiple_of: int = None, **kwargs: Any) -> Type[BaseField]
```
<a name="fields.model_fields.BigInteger.get_column_type"></a>
#### 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
<a name="fields.model_fields.Decimal"></a>
## Decimal Objects
```python
class Decimal(ModelFieldFactory, decimal.Decimal)
```
Decimal field factory that construct Field classes and populated their values.
<a name="fields.model_fields.Decimal._type"></a>
#### \_type
<a name="fields.model_fields.Decimal.__new__"></a>
#### \_\_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]
```
<a name="fields.model_fields.Decimal.get_column_type"></a>
#### 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
<a name="fields.model_fields.Decimal.validate"></a>
#### 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
<a name="fields.model_fields.UUID"></a>
## UUID Objects
```python
class UUID(ModelFieldFactory, uuid.UUID)
```
UUID field factory that construct Field classes and populated their values.
<a name="fields.model_fields.UUID._type"></a>
#### \_type
<a name="fields.model_fields.UUID.__new__"></a>
#### \_\_new\_\_
```python
| __new__(cls, *, uuid_format: str = "hex", **kwargs: Any) -> Type[BaseField]
```
<a name="fields.model_fields.UUID.get_column_type"></a>
#### 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

16
docs/api/index.md Normal file
View File

@ -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.

View File

@ -0,0 +1,64 @@
<a name="models.helpers.models"></a>
# models.helpers.models
<a name="models.helpers.models.populate_default_options_values"></a>
#### 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])`:
<a name="models.helpers.models.extract_annotations_and_default_vals"></a>
#### 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
<a name="models.helpers.models.validate_related_names_in_relations"></a>
#### 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)`:

View File

@ -0,0 +1,122 @@
<a name="models.helpers.pydantic"></a>
# models.helpers.pydantic
<a name="models.helpers.pydantic.create_pydantic_field"></a>
#### 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
<a name="models.helpers.pydantic.get_pydantic_field"></a>
#### 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
<a name="models.helpers.pydantic.populate_default_pydantic_field_value"></a>
#### 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
<a name="models.helpers.pydantic.populate_pydantic_default_values"></a>
#### 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
<a name="models.helpers.pydantic.get_pydantic_base_orm_config"></a>
#### 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.
<a name="models.helpers.pydantic.get_potential_fields"></a>
#### 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

View File

@ -0,0 +1,154 @@
<a name="models.helpers.relations"></a>
# models.helpers.relations
<a name="models.helpers.relations.alias_manager"></a>
#### alias\_manager
<a name="models.helpers.relations.register_relation_on_build"></a>
#### 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
<a name="models.helpers.relations.register_many_to_many_relation_on_build"></a>
#### 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
<a name="models.helpers.relations.expand_reverse_relationships"></a>
#### 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
<a name="models.helpers.relations.register_reverse_model_fields"></a>
#### 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
<a name="models.helpers.relations.register_relation_in_alias_manager"></a>
#### 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
<a name="models.helpers.relations.verify_related_name_dont_duplicate"></a>
#### 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
<a name="models.helpers.relations.reverse_field_not_already_registered"></a>
#### 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

View File

@ -0,0 +1,145 @@
<a name="models.helpers.sqlalchemy"></a>
# models.helpers.sqlalchemy
<a name="models.helpers.sqlalchemy.adjust_through_many_to_many_model"></a>
#### 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
<a name="models.helpers.sqlalchemy.create_and_append_m2m_fk"></a>
#### 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
<a name="models.helpers.sqlalchemy.check_pk_column_validity"></a>
#### 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
<a name="models.helpers.sqlalchemy.sqlalchemy_columns_from_model_fields"></a>
#### 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
<a name="models.helpers.sqlalchemy.populate_meta_tablename_columns_and_pk"></a>
#### 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
<a name="models.helpers.sqlalchemy.populate_meta_sqlalchemy_table_if_required"></a>
#### 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

View File

@ -0,0 +1,90 @@
<a name="models.mixins.alias_mixin"></a>
# models.mixins.alias\_mixin
<a name="models.mixins.alias_mixin.AliasMixin"></a>
## AliasMixin Objects
```python
class AliasMixin()
```
Used to translate field names into database column names.
<a name="models.mixins.alias_mixin.AliasMixin.get_column_alias"></a>
#### 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
<a name="models.mixins.alias_mixin.AliasMixin.get_column_name_from_alias"></a>
#### 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)
<a name="models.mixins.alias_mixin.AliasMixin.translate_columns_to_aliases"></a>
#### 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
<a name="models.mixins.alias_mixin.AliasMixin.translate_aliases_to_columns"></a>
#### 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

View File

@ -0,0 +1,206 @@
<a name="models.mixins.excludable_mixin"></a>
# models.mixins.excludable\_mixin
<a name="models.mixins.excludable_mixin.ExcludableMixin"></a>
## ExcludableMixin Objects
```python
class ExcludableMixin(RelationMixin)
```
Used to include/exclude given set of fields on models during load and dict() calls.
<a name="models.mixins.excludable_mixin.ExcludableMixin.get_child"></a>
#### 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
<a name="models.mixins.excludable_mixin.ExcludableMixin.get_excluded"></a>
#### 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
<a name="models.mixins.excludable_mixin.ExcludableMixin.get_included"></a>
#### 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
<a name="models.mixins.excludable_mixin.ExcludableMixin.is_excluded"></a>
#### 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
<a name="models.mixins.excludable_mixin.ExcludableMixin.is_included"></a>
#### 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
<a name="models.mixins.excludable_mixin.ExcludableMixin._populate_pk_column"></a>
#### \_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
<a name="models.mixins.excludable_mixin.ExcludableMixin.own_table_columns"></a>
#### 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
<a name="models.mixins.excludable_mixin.ExcludableMixin._update_excluded_with_related_not_required"></a>
#### \_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.
<a name="models.mixins.excludable_mixin.ExcludableMixin.get_names_to_exclude"></a>
#### 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

View File

@ -0,0 +1,60 @@
<a name="models.mixins.merge_mixin"></a>
# models.mixins.merge\_mixin
<a name="models.mixins.merge_mixin.MergeModelMixin"></a>
## 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.
<a name="models.mixins.merge_mixin.MergeModelMixin.merge_instances_list"></a>
#### 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
<a name="models.mixins.merge_mixin.MergeModelMixin.merge_two_instances"></a>
#### 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.

View File

@ -0,0 +1,100 @@
<a name="models.mixins.prefetch_mixin"></a>
# models.mixins.prefetch\_mixin
<a name="models.mixins.prefetch_mixin.PrefetchQueryMixin"></a>
## PrefetchQueryMixin Objects
```python
class PrefetchQueryMixin(RelationMixin)
```
Used in PrefetchQuery to extract ids and names of models to prefetch.
<a name="models.mixins.prefetch_mixin.PrefetchQueryMixin.get_clause_target_and_filter_column_name"></a>
#### 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
<a name="models.mixins.prefetch_mixin.PrefetchQueryMixin.get_column_name_for_id_extraction"></a>
#### 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**:
`()`:
<a name="models.mixins.prefetch_mixin.PrefetchQueryMixin.get_related_field_name"></a>
#### 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
<a name="models.mixins.prefetch_mixin.PrefetchQueryMixin.get_filtered_names_to_extract"></a>
#### 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

View File

@ -0,0 +1,93 @@
<a name="models.mixins.relation_mixin"></a>
# models.mixins.relation\_mixin
<a name="models.mixins.relation_mixin.RelationMixin"></a>
## RelationMixin Objects
```python
class RelationMixin()
```
Used to return relation fields/names etc. from given model
<a name="models.mixins.relation_mixin.RelationMixin.extract_db_own_fields"></a>
#### 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
<a name="models.mixins.relation_mixin.RelationMixin.extract_related_fields"></a>
#### 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
<a name="models.mixins.relation_mixin.RelationMixin.extract_related_names"></a>
#### 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
<a name="models.mixins.relation_mixin.RelationMixin._extract_db_related_names"></a>
#### \_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
<a name="models.mixins.relation_mixin.RelationMixin._exclude_related_names_not_required"></a>
#### \_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

View File

@ -0,0 +1,93 @@
<a name="models.mixins.save_mixin"></a>
# models.mixins.save\_mixin
<a name="models.mixins.save_mixin.SavePrepareMixin"></a>
## SavePrepareMixin Objects
```python
class SavePrepareMixin(RelationMixin, AliasMixin)
```
Used to prepare models to be saved in database
<a name="models.mixins.save_mixin.SavePrepareMixin.prepare_model_to_save"></a>
#### 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
<a name="models.mixins.save_mixin.SavePrepareMixin._remove_pk_from_kwargs"></a>
#### \_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
<a name="models.mixins.save_mixin.SavePrepareMixin.substitute_models_with_pks"></a>
#### 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
<a name="models.mixins.save_mixin.SavePrepareMixin.populate_default_values"></a>
#### 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

View File

@ -0,0 +1,340 @@
<a name="models.metaclass"></a>
# models.metaclass
<a name="models.metaclass.PARSED_FIELDS_KEY"></a>
#### PARSED\_FIELDS\_KEY
<a name="models.metaclass.CONFIG_KEY"></a>
#### CONFIG\_KEY
<a name="models.metaclass.ModelMeta"></a>
## 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.
<a name="models.metaclass.ModelMeta.tablename"></a>
#### tablename
<a name="models.metaclass.ModelMeta.table"></a>
#### table
<a name="models.metaclass.ModelMeta.metadata"></a>
#### metadata
<a name="models.metaclass.ModelMeta.database"></a>
#### database
<a name="models.metaclass.ModelMeta.columns"></a>
#### columns
<a name="models.metaclass.ModelMeta.constraints"></a>
#### constraints
<a name="models.metaclass.ModelMeta.pkname"></a>
#### pkname
<a name="models.metaclass.ModelMeta.model_fields"></a>
#### model\_fields
<a name="models.metaclass.ModelMeta.alias_manager"></a>
#### alias\_manager
<a name="models.metaclass.ModelMeta.property_fields"></a>
#### property\_fields
<a name="models.metaclass.ModelMeta.signals"></a>
#### signals
<a name="models.metaclass.ModelMeta.abstract"></a>
#### abstract
<a name="models.metaclass.check_if_field_has_choices"></a>
#### 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
<a name="models.metaclass.choices_validator"></a>
#### 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
<a name="models.metaclass.populate_choices_validators"></a>
#### 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
<a name="models.metaclass.add_cached_properties"></a>
#### 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
<a name="models.metaclass.meta_field_not_set"></a>
#### 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
<a name="models.metaclass.add_property_fields"></a>
#### 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])`:
<a name="models.metaclass.register_signals"></a>
#### 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
<a name="models.metaclass.update_attrs_and_fields"></a>
#### 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
<a name="models.metaclass.verify_constraint_names"></a>
#### 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
<a name="models.metaclass.update_attrs_from_base_meta"></a>
#### 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
<a name="models.metaclass.copy_data_from_parent_model"></a>
#### 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
<a name="models.metaclass.extract_from_parents_definition"></a>
#### 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
<a name="models.metaclass.ModelMetaclass"></a>
## ModelMetaclass Objects
```python
class ModelMetaclass(pydantic.main.ModelMetaclass)
```
<a name="models.metaclass.ModelMetaclass.__new__"></a>
#### \_\_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

View File

@ -0,0 +1,14 @@
<a name="models.modelproxy"></a>
# models.modelproxy
<a name="models.modelproxy.ModelTableProxy"></a>
## 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.

323
docs/api/models/model.md Normal file
View File

@ -0,0 +1,323 @@
<a name="models.model"></a>
# models.model
<a name="models.model.group_related_list"></a>
#### 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
<a name="models.model.T"></a>
#### T
<a name="models.model.Model"></a>
## Model Objects
```python
class Model(NewBaseModel)
```
<a name="models.model.Model.__abstract__"></a>
#### \_\_abstract\_\_
<a name="models.model.Model.__repr__"></a>
#### \_\_repr\_\_
```python
| __repr__() -> str
```
<a name="models.model.Model.from_row"></a>
#### 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
<a name="models.model.Model.populate_nested_models_from_row"></a>
#### 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
<a name="models.model.Model.extract_prefixed_table_columns"></a>
#### 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
<a name="models.model.Model.upsert"></a>
#### 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
<a name="models.model.Model.save"></a>
#### 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
<a name="models.model.Model.save_related"></a>
#### 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
<a name="models.model.Model._update_and_follow"></a>
#### \_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
<a name="models.model.Model.update"></a>
#### 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
<a name="models.model.Model.delete"></a>
#### 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)
<a name="models.model.Model.load"></a>
#### 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

View File

@ -0,0 +1,512 @@
<a name="models.newbasemodel"></a>
# models.newbasemodel
<a name="models.newbasemodel.NewBaseModel"></a>
## 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.
<a name="models.newbasemodel.NewBaseModel.__slots__"></a>
#### \_\_slots\_\_
<a name="models.newbasemodel.NewBaseModel.__init__"></a>
#### \_\_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
<a name="models.newbasemodel.NewBaseModel.__setattr__"></a>
#### \_\_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
<a name="models.newbasemodel.NewBaseModel.__getattribute__"></a>
#### \_\_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
<a name="models.newbasemodel.NewBaseModel._extract_related_model_instead_of_field"></a>
#### \_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
<a name="models.newbasemodel.NewBaseModel.__eq__"></a>
#### \_\_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
<a name="models.newbasemodel.NewBaseModel.__same__"></a>
#### \_\_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
<a name="models.newbasemodel.NewBaseModel.get_name"></a>
#### 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
<a name="models.newbasemodel.NewBaseModel.pk_column"></a>
#### 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
<a name="models.newbasemodel.NewBaseModel.saved"></a>
#### saved
```python
| @property
| saved() -> bool
```
Saved status of the model. Changed by setattr and loading from db
<a name="models.newbasemodel.NewBaseModel.signals"></a>
#### signals
```python
| @property
| signals() -> "SignalEmitter"
```
Exposes signals from model Meta
<a name="models.newbasemodel.NewBaseModel.pk_type"></a>
#### pk\_type
```python
| @classmethod
| pk_type(cls) -> Any
```
Shortcut to models primary key field type
<a name="models.newbasemodel.NewBaseModel.db_backend_name"></a>
#### db\_backend\_name
```python
| @classmethod
| db_backend_name(cls) -> str
```
Shortcut to database dialect,
cause some dialect require different treatment
<a name="models.newbasemodel.NewBaseModel.remove"></a>
#### remove
```python
| remove(parent: "T", name: str) -> None
```
Removes child from relation with given name in RelationshipManager
<a name="models.newbasemodel.NewBaseModel.set_save_status"></a>
#### set\_save\_status
```python
| set_save_status(status: bool) -> None
```
Sets value of the save status
<a name="models.newbasemodel.NewBaseModel.get_properties"></a>
#### 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
<a name="models.newbasemodel.NewBaseModel._get_related_not_excluded_fields"></a>
#### \_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)`:
<a name="models.newbasemodel.NewBaseModel._extract_nested_models_from_list"></a>
#### \_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
<a name="models.newbasemodel.NewBaseModel._skip_ellipsis"></a>
#### \_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
<a name="models.newbasemodel.NewBaseModel._extract_nested_models"></a>
#### \_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
<a name="models.newbasemodel.NewBaseModel.dict"></a>
#### 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**:
`()`:
<a name="models.newbasemodel.NewBaseModel.update_from_dict"></a>
#### 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
<a name="models.newbasemodel.NewBaseModel._convert_json"></a>
#### \_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
<a name="models.newbasemodel.NewBaseModel._is_conversion_to_json_needed"></a>
#### \_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
<a name="models.newbasemodel.NewBaseModel._extract_own_model_fields"></a>
#### \_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.
<a name="models.newbasemodel.NewBaseModel._extract_model_db_fields"></a>
#### \_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.
<a name="models.newbasemodel.NewBaseModel.get_relation_model_id"></a>
#### 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

View File

@ -0,0 +1,174 @@
<a name="queryset.clause"></a>
# queryset.clause
<a name="queryset.clause.FILTER_OPERATORS"></a>
#### FILTER\_OPERATORS
<a name="queryset.clause.ESCAPE_CHARACTERS"></a>
#### ESCAPE\_CHARACTERS
<a name="queryset.clause.QueryClause"></a>
## QueryClause Objects
```python
class QueryClause()
```
Constructs where clauses from strings passed as arguments
<a name="queryset.clause.QueryClause.__init__"></a>
#### \_\_init\_\_
```python
| __init__(model_cls: Type["Model"], filter_clauses: List, select_related: List) -> None
```
<a name="queryset.clause.QueryClause.filter"></a>
#### 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
<a name="queryset.clause.QueryClause._populate_filter_clauses"></a>
#### \_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
<a name="queryset.clause.QueryClause._process_column_clause_for_operator_and_value"></a>
#### \_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
<a name="queryset.clause.QueryClause._determine_filter_target_table"></a>
#### \_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
<a name="queryset.clause.QueryClause._compile_clause"></a>
#### \_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
<a name="queryset.clause.QueryClause._escape_characters_in_clause"></a>
#### \_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
<a name="queryset.clause.QueryClause._extract_operator_field_and_related"></a>
#### \_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

View File

@ -0,0 +1,36 @@
<a name="queryset.filter_query"></a>
# queryset.filter\_query
<a name="queryset.filter_query.FilterQuery"></a>
## FilterQuery Objects
```python
class FilterQuery()
```
Modifies the select query with given list of where/filter clauses.
<a name="queryset.filter_query.FilterQuery.__init__"></a>
#### \_\_init\_\_
```python
| __init__(filter_clauses: List, exclude: bool = False) -> None
```
<a name="queryset.filter_query.FilterQuery.apply"></a>
#### 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

262
docs/api/query-set/join.md Normal file
View File

@ -0,0 +1,262 @@
<a name="queryset.join"></a>
# queryset.join
<a name="queryset.join.JoinParameters"></a>
## JoinParameters Objects
```python
class JoinParameters(NamedTuple)
```
Named tuple that holds set of parameters passed during join construction.
<a name="queryset.join.JoinParameters.prev_model"></a>
#### prev\_model
<a name="queryset.join.JoinParameters.previous_alias"></a>
#### previous\_alias
<a name="queryset.join.JoinParameters.from_table"></a>
#### from\_table
<a name="queryset.join.JoinParameters.model_cls"></a>
#### model\_cls
<a name="queryset.join.SqlJoin"></a>
## SqlJoin Objects
```python
class SqlJoin()
```
<a name="queryset.join.SqlJoin.__init__"></a>
#### \_\_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
```
<a name="queryset.join.SqlJoin.alias_manager"></a>
#### 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
<a name="queryset.join.SqlJoin.on_clause"></a>
#### 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
<a name="queryset.join.SqlJoin.update_inclusions"></a>
#### 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
<a name="queryset.join.SqlJoin.build_join"></a>
#### 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
<a name="queryset.join.SqlJoin._build_join_parameters"></a>
#### \_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
<a name="queryset.join.SqlJoin._process_join"></a>
#### \_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
<a name="queryset.join.SqlJoin._switch_many_to_many_order_columns"></a>
#### \_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
<a name="queryset.join.SqlJoin._check_if_condition_apply"></a>
#### \_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
<a name="queryset.join.SqlJoin.set_aliased_order_by"></a>
#### 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
<a name="queryset.join.SqlJoin.get_order_bys"></a>
#### 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
<a name="queryset.join.SqlJoin.get_to_and_from_keys"></a>
#### 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

View File

@ -0,0 +1,36 @@
<a name="queryset.limit_query"></a>
# queryset.limit\_query
<a name="queryset.limit_query.LimitQuery"></a>
## LimitQuery Objects
```python
class LimitQuery()
```
Modifies the select query with limit clause.
<a name="queryset.limit_query.LimitQuery.__init__"></a>
#### \_\_init\_\_
```python
| __init__(limit_count: Optional[int]) -> None
```
<a name="queryset.limit_query.LimitQuery.apply"></a>
#### 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

View File

@ -0,0 +1,36 @@
<a name="queryset.offset_query"></a>
# queryset.offset\_query
<a name="queryset.offset_query.OffsetQuery"></a>
## OffsetQuery Objects
```python
class OffsetQuery()
```
Modifies the select query with offset if set
<a name="queryset.offset_query.OffsetQuery.__init__"></a>
#### \_\_init\_\_
```python
| __init__(query_offset: Optional[int]) -> None
```
<a name="queryset.offset_query.OffsetQuery.apply"></a>
#### 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

View File

@ -0,0 +1,36 @@
<a name="queryset.order_query"></a>
# queryset.order\_query
<a name="queryset.order_query.OrderQuery"></a>
## OrderQuery Objects
```python
class OrderQuery()
```
Modifies the select query with given list of order_by clauses.
<a name="queryset.order_query.OrderQuery.__init__"></a>
#### \_\_init\_\_
```python
| __init__(sorted_orders: Dict) -> None
```
<a name="queryset.order_query.OrderQuery.apply"></a>
#### 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

View File

@ -0,0 +1,352 @@
<a name="queryset.prefetch_query"></a>
# queryset.prefetch\_query
<a name="queryset.prefetch_query.add_relation_field_to_fields"></a>
#### 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
<a name="queryset.prefetch_query.sort_models"></a>
#### 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
<a name="queryset.prefetch_query.set_children_on_model"></a>
#### 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
<a name="queryset.prefetch_query.PrefetchQuery"></a>
## 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.
<a name="queryset.prefetch_query.PrefetchQuery.__init__"></a>
#### \_\_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
```
<a name="queryset.prefetch_query.PrefetchQuery.prefetch_related"></a>
#### 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
<a name="queryset.prefetch_query.PrefetchQuery._extract_ids_from_raw_data"></a>
#### \_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
<a name="queryset.prefetch_query.PrefetchQuery._extract_ids_from_preloaded_models"></a>
#### \_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
<a name="queryset.prefetch_query.PrefetchQuery._extract_required_ids"></a>
#### \_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
<a name="queryset.prefetch_query.PrefetchQuery._get_filter_for_prefetch"></a>
#### \_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])`:
<a name="queryset.prefetch_query.PrefetchQuery._populate_nested_related"></a>
#### \_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
<a name="queryset.prefetch_query.PrefetchQuery._prefetch_related_models"></a>
#### \_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
<a name="queryset.prefetch_query.PrefetchQuery._extract_related_models"></a>
#### \_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
<a name="queryset.prefetch_query.PrefetchQuery._run_prefetch_query"></a>
#### \_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
<a name="queryset.prefetch_query.PrefetchQuery._get_select_related_if_apply"></a>
#### \_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
<a name="queryset.prefetch_query.PrefetchQuery._update_already_loaded_rows"></a>
#### \_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
<a name="queryset.prefetch_query.PrefetchQuery._populate_rows"></a>
#### \_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

View File

@ -0,0 +1,671 @@
<a name="queryset.queryset"></a>
# queryset.queryset
<a name="queryset.queryset.QuerySet"></a>
## QuerySet Objects
```python
class QuerySet()
```
Main class to perform database queries, exposed on each model as objects attribute.
<a name="queryset.queryset.QuerySet.__init__"></a>
#### \_\_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
```
<a name="queryset.queryset.QuerySet.__get__"></a>
#### \_\_get\_\_
```python
| __get__(instance: Optional[Union["QuerySet", "QuerysetProxy"]], owner: Union[Type["Model"], Type["QuerysetProxy"]]) -> "QuerySet"
```
<a name="queryset.queryset.QuerySet.model_meta"></a>
#### 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
<a name="queryset.queryset.QuerySet.model"></a>
#### model
```python
| @property
| model() -> Type["Model"]
```
Shortcut to model class set on QuerySet.
**Returns**:
`(Type[Model])`: model class
<a name="queryset.queryset.QuerySet._prefetch_related_models"></a>
#### \_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
<a name="queryset.queryset.QuerySet._process_query_result_rows"></a>
#### \_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
<a name="queryset.queryset.QuerySet.check_single_result_rows_count"></a>
#### 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
<a name="queryset.queryset.QuerySet.database"></a>
#### database
```python
| @property
| database() -> databases.Database
```
Shortcut to models database from Meta class.
**Returns**:
`(databases.Database)`: database
<a name="queryset.queryset.QuerySet.table"></a>
#### table
```python
| @property
| table() -> sqlalchemy.Table
```
Shortcut to models table from Meta class.
**Returns**:
`(sqlalchemy.Table)`: database table
<a name="queryset.queryset.QuerySet.build_select_expression"></a>
#### 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
<a name="queryset.queryset.QuerySet.filter"></a>
#### 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
<a name="queryset.queryset.QuerySet.exclude"></a>
#### 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
<a name="queryset.queryset.QuerySet.select_related"></a>
#### 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
<a name="queryset.queryset.QuerySet.prefetch_related"></a>
#### 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
<a name="queryset.queryset.QuerySet.fields"></a>
#### 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
<a name="queryset.queryset.QuerySet.exclude_fields"></a>
#### 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
<a name="queryset.queryset.QuerySet.order_by"></a>
#### 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
<a name="queryset.queryset.QuerySet.exists"></a>
#### 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
<a name="queryset.queryset.QuerySet.count"></a>
#### 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
<a name="queryset.queryset.QuerySet.update"></a>
#### 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
<a name="queryset.queryset.QuerySet.delete"></a>
#### 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
<a name="queryset.queryset.QuerySet.limit"></a>
#### 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
<a name="queryset.queryset.QuerySet.offset"></a>
#### 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
<a name="queryset.queryset.QuerySet.first"></a>
#### 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
<a name="queryset.queryset.QuerySet.get"></a>
#### 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
<a name="queryset.queryset.QuerySet.get_or_create"></a>
#### 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
<a name="queryset.queryset.QuerySet.update_or_create"></a>
#### 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
<a name="queryset.queryset.QuerySet.all"></a>
#### 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
<a name="queryset.queryset.QuerySet.create"></a>
#### 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
<a name="queryset.queryset.QuerySet.bulk_create"></a>
#### 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.
<a name="queryset.queryset.QuerySet.bulk_update"></a>
#### 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

157
docs/api/query-set/query.md Normal file
View File

@ -0,0 +1,157 @@
<a name="queryset.query"></a>
# queryset.query
<a name="queryset.query.Query"></a>
## Query Objects
```python
class Query()
```
<a name="queryset.query.Query.__init__"></a>
#### \_\_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
```
<a name="queryset.query.Query._init_sorted_orders"></a>
#### \_init\_sorted\_orders
```python
| _init_sorted_orders() -> None
```
Initialize empty order_by dict to be populated later during the query call
<a name="queryset.query.Query.prefixed_pk_name"></a>
#### 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.
<a name="queryset.query.Query.alias"></a>
#### 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
<a name="queryset.query.Query.apply_order_bys_for_primary_model"></a>
#### 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.
<a name="queryset.query.Query._pagination_query_required"></a>
#### \_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
<a name="queryset.query.Query.build_select_expression"></a>
#### 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.
<a name="queryset.query.Query._build_pagination_subquery"></a>
#### \_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
<a name="queryset.query.Query._apply_expression_modifiers"></a>
#### \_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
<a name="queryset.query.Query._reset_query_parameters"></a>
#### \_reset\_query\_parameters
```python
| _reset_query_parameters() -> None
```
Although it should be created each time before the call we reset the key params
anyway.

152
docs/api/query-set/utils.md Normal file
View File

@ -0,0 +1,152 @@
<a name="queryset.utils"></a>
# queryset.utils
<a name="queryset.utils.check_node_not_dict_or_not_last_node"></a>
#### 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
<a name="queryset.utils.translate_list_to_dict"></a>
#### 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
<a name="queryset.utils.convert_set_to_required_dict"></a>
#### 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
<a name="queryset.utils.update"></a>
#### 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
<a name="queryset.utils.update_dict_from_list"></a>
#### 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
<a name="queryset.utils.extract_nested_models"></a>
#### 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
<a name="queryset.utils.extract_models_to_dict_of_lists"></a>
#### 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

View File

@ -0,0 +1,127 @@
<a name="relations.alias_manager"></a>
# relations.alias\_manager
<a name="relations.alias_manager.get_table_alias"></a>
#### 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
<a name="relations.alias_manager.AliasManager"></a>
## AliasManager Objects
```python
class AliasManager()
```
Keep all aliases of relations between different tables.
One global instance is shared between all models.
<a name="relations.alias_manager.AliasManager.__init__"></a>
#### \_\_init\_\_
```python
| __init__() -> None
```
<a name="relations.alias_manager.AliasManager.prefixed_columns"></a>
#### 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"
<a name="relations.alias_manager.AliasManager.prefixed_table_name"></a>
#### 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"
<a name="relations.alias_manager.AliasManager.add_relation_type"></a>
#### 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
<a name="relations.alias_manager.AliasManager.resolve_relation_alias"></a>
#### 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

View File

@ -0,0 +1,595 @@
<a name="relations.querysetproxy"></a>
# relations.querysetproxy
<a name="relations.querysetproxy.QuerysetProxy"></a>
## QuerysetProxy Objects
```python
class QuerysetProxy(ormar.QuerySetProtocol)
```
Exposes QuerySet methods on relations, but also handles creating and removing
of through Models for m2m relations.
<a name="relations.querysetproxy.QuerysetProxy.__init__"></a>
#### \_\_init\_\_
```python
| __init__(relation: "Relation", type_: "RelationType", qryset: "QuerySet" = None) -> None
```
<a name="relations.querysetproxy.QuerysetProxy.queryset"></a>
#### queryset
```python
| @property
| queryset() -> "QuerySet"
```
Returns queryset if it's set, AttributeError otherwise.
**Returns**:
`(QuerySet)`: QuerySet
<a name="relations.querysetproxy.QuerysetProxy.queryset"></a>
#### queryset
```python
| @queryset.setter
| queryset(value: "QuerySet") -> None
```
Set's the queryset. Initialized in RelationProxy.
**Arguments**:
- `value (QuerySet)`: QuerySet
<a name="relations.querysetproxy.QuerysetProxy._assign_child_to_parent"></a>
#### \_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.
<a name="relations.querysetproxy.QuerysetProxy._register_related"></a>
#### \_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.
<a name="relations.querysetproxy.QuerysetProxy._clean_items_on_load"></a>
#### \_clean\_items\_on\_load
```python
| _clean_items_on_load() -> None
```
Cleans the current list of the related models.
<a name="relations.querysetproxy.QuerysetProxy.create_through_instance"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.delete_through_instance"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.exists"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.count"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.clear"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.first"></a>
#### 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)`:
<a name="relations.querysetproxy.QuerysetProxy.get"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.all"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.create"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.get_or_create"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.update_or_create"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.filter"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.exclude"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.select_related"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.prefetch_related"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.limit"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.offset"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.fields"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.exclude_fields"></a>
#### 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
<a name="relations.querysetproxy.QuerysetProxy.order_by"></a>
#### 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

View File

@ -0,0 +1,159 @@
<a name="relations.relation_manager"></a>
# relations.relation\_manager
<a name="relations.relation_manager.RelationsManager"></a>
## RelationsManager Objects
```python
class RelationsManager()
```
Manages relations on a Model, each Model has it's own instance.
<a name="relations.relation_manager.RelationsManager.__init__"></a>
#### \_\_init\_\_
```python
| __init__(related_fields: List[Type[ForeignKeyField]] = None, owner: "NewBaseModel" = None) -> None
```
<a name="relations.relation_manager.RelationsManager._get_relation_type"></a>
#### \_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
<a name="relations.relation_manager.RelationsManager._add_relation"></a>
#### \_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
<a name="relations.relation_manager.RelationsManager.__contains__"></a>
#### \_\_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
<a name="relations.relation_manager.RelationsManager.get"></a>
#### 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
<a name="relations.relation_manager.RelationsManager._get"></a>
#### \_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
<a name="relations.relation_manager.RelationsManager.add"></a>
#### 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
<a name="relations.relation_manager.RelationsManager.remove"></a>
#### 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
<a name="relations.relation_manager.RelationsManager.remove_parent"></a>
#### 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

View File

@ -0,0 +1,151 @@
<a name="relations.relation_proxy"></a>
# relations.relation\_proxy
<a name="relations.relation_proxy.RelationProxy"></a>
## RelationProxy Objects
```python
class RelationProxy(list)
```
Proxy of the Relation that is a list with special methods.
<a name="relations.relation_proxy.RelationProxy.__init__"></a>
#### \_\_init\_\_
```python
| __init__(relation: "Relation", type_: "RelationType", field_name: str, data_: Any = None) -> None
```
<a name="relations.relation_proxy.RelationProxy.related_field_name"></a>
#### 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
<a name="relations.relation_proxy.RelationProxy.__getattribute__"></a>
#### \_\_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
<a name="relations.relation_proxy.RelationProxy.__getattr__"></a>
#### \_\_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
<a name="relations.relation_proxy.RelationProxy._initialize_queryset"></a>
#### \_initialize\_queryset
```python
| _initialize_queryset() -> None
```
Initializes the QuerySetProxy if not yet initialized.
<a name="relations.relation_proxy.RelationProxy._check_if_queryset_is_initialized"></a>
#### \_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
<a name="relations.relation_proxy.RelationProxy._check_if_model_saved"></a>
#### \_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.
<a name="relations.relation_proxy.RelationProxy._set_queryset"></a>
#### \_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
<a name="relations.relation_proxy.RelationProxy.remove"></a>
#### 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
<a name="relations.relation_proxy.RelationProxy.add"></a>
#### 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

View File

@ -0,0 +1,128 @@
<a name="relations.relation"></a>
# relations.relation
<a name="relations.relation.RelationType"></a>
## RelationType Objects
```python
class RelationType(Enum)
```
Different types of relations supported by ormar:
* ForeignKey = PRIMARY
* reverse ForeignKey = REVERSE
* ManyToMany = MULTIPLE
<a name="relations.relation.RelationType.PRIMARY"></a>
#### PRIMARY
<a name="relations.relation.RelationType.REVERSE"></a>
#### REVERSE
<a name="relations.relation.RelationType.MULTIPLE"></a>
#### MULTIPLE
<a name="relations.relation.Relation"></a>
## Relation Objects
```python
class Relation()
```
Keeps related Models and handles adding/removing of the children.
<a name="relations.relation.Relation.__init__"></a>
#### \_\_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
<a name="relations.relation.Relation._clean_related"></a>
#### \_clean\_related
```python
| _clean_related() -> None
```
Removes dead weakrefs from RelationProxy.
<a name="relations.relation.Relation._find_existing"></a>
#### \_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
<a name="relations.relation.Relation.add"></a>
#### 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
<a name="relations.relation.Relation.remove"></a>
#### 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
<a name="relations.relation.Relation.get"></a>
#### 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
<a name="relations.relation.Relation.__repr__"></a>
#### \_\_repr\_\_
```python
| __repr__() -> str
```

View File

@ -0,0 +1,26 @@
<a name="relations.utils"></a>
# relations.utils
<a name="relations.utils.get_relations_sides_and_names"></a>
#### 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

View File

@ -0,0 +1,130 @@
<a name="decorators.signals"></a>
# decorators.signals
<a name="decorators.signals.receiver"></a>
#### 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
<a name="decorators.signals.post_save"></a>
#### 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
<a name="decorators.signals.post_update"></a>
#### 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
<a name="decorators.signals.post_delete"></a>
#### 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
<a name="decorators.signals.pre_save"></a>
#### 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
<a name="decorators.signals.pre_update"></a>
#### 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
<a name="decorators.signals.pre_delete"></a>
#### 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

143
docs/api/signals/signal.md Normal file
View File

@ -0,0 +1,143 @@
<a name="signals"></a>
# 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.
<a name="signals.__all__"></a>
#### \_\_all\_\_
<a name="signals.signal"></a>
# signals.signal
<a name="signals.signal.callable_accepts_kwargs"></a>
#### 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
<a name="signals.signal.make_id"></a>
#### 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
<a name="signals.signal.Signal"></a>
## Signal Objects
```python
class Signal()
```
Signal that notifies all receiver functions.
In ormar used by models to send pre_save, post_save etc. signals.
<a name="signals.signal.Signal.__init__"></a>
#### \_\_init\_\_
```python
| __init__() -> None
```
<a name="signals.signal.Signal.connect"></a>
#### 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
<a name="signals.signal.Signal.disconnect"></a>
#### 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
<a name="signals.signal.Signal.send"></a>
#### 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
<a name="signals.signal.SignalEmitter"></a>
## 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.
<a name="signals.signal.SignalEmitter.__init__"></a>
#### \_\_init\_\_
```python
| __init__() -> None
```
<a name="signals.signal.SignalEmitter.__getattr__"></a>
#### \_\_getattr\_\_
```python
| __getattr__(item: str) -> Signal
```
<a name="signals.signal.SignalEmitter.__setattr__"></a>
#### \_\_setattr\_\_
```python
| __setattr__(key: str, value: Any) -> None
```

View File

@ -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