update docs, add load_all(), tests for load_all, make through field optional

This commit is contained in:
collerek
2021-03-03 19:48:40 +01:00
parent 9ad1528cc0
commit a8ae50276e
56 changed files with 1653 additions and 653 deletions

View File

@ -72,6 +72,27 @@ Excludes defaults and alias as they are populated separately
`(bool)`: True if field is present on pydantic.FieldInfo
<a name="fields.base.BaseField.get_base_pydantic_field_info"></a>
#### get\_base\_pydantic\_field\_info
```python
| @classmethod
| get_base_pydantic_field_info(cls, allow_null: bool) -> FieldInfo
```
Generates base pydantic.FieldInfo with only default and optionally
required to fix pydantic Json field being set to required=False.
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)`: instance of base pydantic.FieldInfo
<a name="fields.base.BaseField.convert_to_pydantic_field_info"></a>
#### convert\_to\_pydantic\_field\_info

View File

@ -332,3 +332,32 @@ Selects the appropriate constructor based on a passed value.
`(Optional[Union["Model", List["Model"]]])`: returns a Model or a list of Models
<a name="fields.foreign_key.ForeignKeyField.get_relation_name"></a>
#### get\_relation\_name
```python
| @classmethod
| get_relation_name(cls) -> str
```
Returns name of the relation, which can be a own name or through model
names for m2m models
**Returns**:
`(bool)`: result of the check
<a name="fields.foreign_key.ForeignKeyField.get_source_model"></a>
#### get\_source\_model
```python
| @classmethod
| get_source_model(cls) -> Type["Model"]
```
Returns model from which the relation comes -> either owner or through model
**Returns**:
`(Type["Model"])`: source model

View File

@ -24,7 +24,7 @@ pydantic field to use and type of the target column field.
#### ManyToMany
```python
ManyToMany(to: "ToType", through: "ToType", *, name: str = None, unique: bool = False, virtual: bool = False, **kwargs: Any, ,) -> Any
ManyToMany(to: "ToType", through: Optional["ToType"] = None, *, name: str = None, unique: bool = False, virtual: bool = False, **kwargs: Any, ,) -> Any
```
Despite a name it's a function that returns constructed ManyToManyField.
@ -134,3 +134,42 @@ Evaluates the ForwardRef to actual Field based on global and local namespaces
`(None)`: None
<a name="fields.many_to_many.ManyToManyField.get_relation_name"></a>
#### get\_relation\_name
```python
| @classmethod
| get_relation_name(cls) -> str
```
Returns name of the relation, which can be a own name or through model
names for m2m models
**Returns**:
`(bool)`: result of the check
<a name="fields.many_to_many.ManyToManyField.get_source_model"></a>
#### get\_source\_model
```python
| @classmethod
| get_source_model(cls) -> Type["Model"]
```
Returns model from which the relation comes -> either owner or through model
**Returns**:
`(Type["Model"])`: source model
<a name="fields.many_to_many.ManyToManyField.create_default_through_model"></a>
#### create\_default\_through\_model
```python
| @classmethod
| create_default_through_model(cls) -> None
```
Creates default empty through model if no additional fields are required.

View File

@ -0,0 +1,188 @@
<a name="models.excludable"></a>
# models.excludable
<a name="models.excludable.Excludable"></a>
## Excludable Objects
```python
@dataclass
class Excludable()
```
Class that keeps sets of fields to exclude and include
<a name="models.excludable.Excludable.get_copy"></a>
#### get\_copy
```python
| get_copy() -> "Excludable"
```
Return copy of self to avoid in place modifications
**Returns**:
`(ormar.models.excludable.Excludable)`: copy of self with copied sets
<a name="models.excludable.Excludable.set_values"></a>
#### set\_values
```python
| set_values(value: Set, is_exclude: bool) -> None
```
Appends the data to include/exclude sets.
**Arguments**:
- `value (set)`: set of values to add
- `is_exclude (bool)`: flag if values are to be excluded or included
<a name="models.excludable.Excludable.is_included"></a>
#### is\_included
```python
| is_included(key: str) -> bool
```
Check if field in included (in set or set is {...})
**Arguments**:
- `key (str)`: key to check
**Returns**:
`(bool)`: result of the check
<a name="models.excludable.Excludable.is_excluded"></a>
#### is\_excluded
```python
| is_excluded(key: str) -> bool
```
Check if field in excluded (in set or set is {...})
**Arguments**:
- `key (str)`: key to check
**Returns**:
`(bool)`: result of the check
<a name="models.excludable.ExcludableItems"></a>
## ExcludableItems Objects
```python
class ExcludableItems()
```
Keeps a dictionary of Excludables by alias + model_name keys
to allow quick lookup by nested models without need to travers
deeply nested dictionaries and passing include/exclude around
<a name="models.excludable.ExcludableItems.from_excludable"></a>
#### from\_excludable
```python
| @classmethod
| from_excludable(cls, other: "ExcludableItems") -> "ExcludableItems"
```
Copy passed ExcludableItems to avoid inplace modifications.
**Arguments**:
- `other (ormar.models.excludable.ExcludableItems)`: other excludable items to be copied
**Returns**:
`(ormar.models.excludable.ExcludableItems)`: copy of other
<a name="models.excludable.ExcludableItems.get"></a>
#### get
```python
| get(model_cls: Type["Model"], alias: str = "") -> Excludable
```
Return Excludable for given model and alias.
**Arguments**:
- `model_cls (ormar.models.metaclass.ModelMetaclass)`: target model to check
- `alias (str)`: table alias from relation manager
**Returns**:
`(ormar.models.excludable.Excludable)`: Excludable for given model and alias
<a name="models.excludable.ExcludableItems.build"></a>
#### build
```python
| build(items: Union[List[str], str, Tuple[str], Set[str], Dict], model_cls: Type["Model"], is_exclude: bool = False) -> None
```
Receives the one of the types of items and parses them as to achieve
a end situation with one excludable per alias/model in relation.
Each excludable has two sets of values - one to include, one to exclude.
**Arguments**:
- `items (Union[List[str], str, Tuple[str], Set[str], Dict])`: values to be included or excluded
- `model_cls (ormar.models.metaclass.ModelMetaclass)`: source model from which relations are constructed
- `is_exclude (bool)`: flag if items should be included or excluded
<a name="models.excludable.ExcludableItems._set_excludes"></a>
#### \_set\_excludes
```python
| _set_excludes(items: Set, model_name: str, is_exclude: bool, alias: str = "") -> None
```
Sets set of values to be included or excluded for given key and model.
**Arguments**:
- `items (set)`: items to include/exclude
- `model_name (str)`: name of model to construct key
- `is_exclude (bool)`: flag if values should be included or excluded
- `alias (str)`:
<a name="models.excludable.ExcludableItems._traverse_dict"></a>
#### \_traverse\_dict
```python
| _traverse_dict(values: Dict, source_model: Type["Model"], model_cls: Type["Model"], is_exclude: bool, related_items: List = None, alias: str = "") -> None
```
Goes through dict of nested values and construct/update Excludables.
**Arguments**:
- `values (Dict)`: items to include/exclude
- `source_model (ormar.models.metaclass.ModelMetaclass)`: source model from which relations are constructed
- `model_cls (ormar.models.metaclass.ModelMetaclass)`: model from which current relation is constructed
- `is_exclude (bool)`: flag if values should be included or excluded
- `related_items (List)`: list of names of related fields chain
- `alias (str)`: alias of relation
<a name="models.excludable.ExcludableItems._traverse_list"></a>
#### \_traverse\_list
```python
| _traverse_list(values: Set[str], model_cls: Type["Model"], is_exclude: bool) -> None
```
Goes through list of values and construct/update Excludables.
**Arguments**:
- `values (set)`: items to include/exclude
- `model_cls (ormar.models.metaclass.ModelMetaclass)`: model from which current relation is constructed
- `is_exclude (bool)`: flag if values should be included or excluded

View File

@ -87,28 +87,6 @@ extraction of ormar model_fields.
`(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)`:
<a name="models.helpers.models.group_related_list"></a>
#### group\_related\_list
@ -134,3 +112,23 @@ Result dictionary is sorted by length of the values and by key
`(Dict[str, List])`: list converted to dictionary to avoid repetition and group nested models
<a name="models.helpers.models.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

View File

@ -5,7 +5,7 @@
#### create\_pydantic\_field
```python
create_pydantic_field(field_name: str, model: Type["Model"], model_field: Type[ManyToManyField]) -> None
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
@ -42,7 +42,7 @@ field_name. Returns a pydantic field with type of field_name field type.
#### populate\_default\_pydantic\_field\_value
```python
populate_default_pydantic_field_value(ormar_field: Type[BaseField], field_name: str, attrs: dict) -> dict
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
@ -94,7 +94,7 @@ Those annotations are later used by pydantic to construct it's own fields.
#### get\_pydantic\_base\_orm\_config
```python
get_pydantic_base_orm_config() -> Type[BaseConfig]
get_pydantic_base_orm_config() -> Type[pydantic.BaseConfig]
```
Returns empty pydantic Config with orm_mode set to True.

View File

@ -0,0 +1,25 @@
<a name="models.helpers.related_names_validation"></a>
# models.helpers.related\_names\_validation
<a name="models.helpers.related_names_validation.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

@ -23,7 +23,7 @@ aliases for proper sql joins.
#### register\_many\_to\_many\_relation\_on\_build
```python
register_many_to_many_relation_on_build(field: Type[ManyToManyField]) -> None
register_many_to_many_relation_on_build(field: Type["ManyToManyField"]) -> None
```
Registers connection between through model and both sides of the m2m relation.
@ -89,11 +89,24 @@ Autogenerated reverse fields also set related_name to the original field name.
- `model_field (relation Field)`: original relation ForeignKey field
<a name="models.helpers.relations.register_through_shortcut_fields"></a>
#### register\_through\_shortcut\_fields
```python
register_through_shortcut_fields(model_field: Type["ManyToManyField"]) -> None
```
Registers m2m relation through shortcut on both ends of the relation.
**Arguments**:
- `model_field (ManyToManyField)`: relation field defined in parent model
<a name="models.helpers.relations.register_relation_in_alias_manager"></a>
#### register\_relation\_in\_alias\_manager
```python
register_relation_in_alias_manager(field: Type[ForeignKeyField]) -> None
register_relation_in_alias_manager(field: Type["ForeignKeyField"]) -> None
```
Registers the relation (and reverse relation) in alias manager.

View File

@ -5,7 +5,7 @@
#### adjust\_through\_many\_to\_many\_model
```python
adjust_through_many_to_many_model(model_field: Type[ManyToManyField]) -> None
adjust_through_many_to_many_model(model_field: Type["ManyToManyField"]) -> None
```
Registers m2m relation on through model.
@ -21,7 +21,7 @@ Sets pydantic fields with child and parent model types.
#### create\_and\_append\_m2m\_fk
```python
create_and_append_m2m_fk(model: Type["Model"], model_field: Type[ManyToManyField], field_name: str) -> None
create_and_append_m2m_fk(model: Type["Model"], model_field: Type["ManyToManyField"], field_name: str) -> None
```
Registers sqlalchemy Column with sqlalchemy.ForeignKey leading to the model.
@ -38,7 +38,7 @@ Newly created field is added to m2m relation through model Meta columns and tabl
#### check\_pk\_column\_validity
```python
check_pk_column_validity(field_name: str, field: BaseField, pkname: Optional[str]) -> Optional[str]
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
@ -165,7 +165,7 @@ It populates name, metadata, columns and constraints.
#### update\_column\_definition
```python
update_column_definition(model: Union[Type["Model"], Type["NewBaseModel"]], field: Type[ForeignKeyField]) -> None
update_column_definition(model: Union[Type["Model"], Type["NewBaseModel"]], field: Type["ForeignKeyField"]) -> None
```
Updates a column with a new type column based on updated parameters in FK fields.

View File

@ -0,0 +1,120 @@
<a name="models.helpers.validation"></a>
# models.helpers.validation
<a name="models.helpers.validation.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.helpers.validation.convert_choices_if_needed"></a>
#### convert\_choices\_if\_needed
```python
convert_choices_if_needed(field: Type["BaseField"], value: Any) -> Tuple[Any, List]
```
Converts dates to isoformat as fastapi can check this condition in routes
and the fields are not yet parsed.
Converts enums to list of it's values.
Converts uuids to strings.
Converts decimal to float with given scale.
**Arguments**:
- `field (Type[BaseField])`: ormar field to check with choices
- `values (Dict)`: current values of the model to verify
**Returns**:
`(Tuple[Any, List])`: value, choices list
<a name="models.helpers.validation.validate_choices"></a>
#### validate\_choices
```python
validate_choices(field: Type["BaseField"], value: Any) -> None
```
Validates if given value is in provided choices.
**Raises**:
- `ValueError`: If value is not in choices.
**Arguments**:
- `field (Type[BaseField])`: field to validate
- `value (Any)`: value of the field
<a name="models.helpers.validation.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.helpers.validation.construct_modify_schema_function"></a>
#### construct\_modify\_schema\_function
```python
construct_modify_schema_function(fields_with_choices: List) -> SchemaExtraCallable
```
Modifies the schema to include fields with choices validator.
Those fields will be displayed in schema as Enum types with available choices
values listed next to them.
**Arguments**:
- `fields_with_choices (List)`: list of fields with choices validation
**Returns**:
`(Callable)`: callable that will be run by pydantic to modify the schema
<a name="models.helpers.validation.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

View File

@ -30,88 +30,12 @@ passed items.
`(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]
| _populate_pk_column(model: Union[Type["Model"], Type["ModelRow"]], columns: List[str], use_alias: bool = False) -> List[str]
```
Adds primary key column/alias (depends on use_alias flag) to list of
@ -132,7 +56,7 @@ column names that are selected.
```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]
| own_table_columns(cls, model: Union[Type["Model"], Type["ModelRow"]], excludable: ExcludableItems, alias: str = "", use_alias: bool = False) -> List[str]
```
Returns list of aliases or field names for given model.
@ -145,9 +69,9 @@ Primary key field is always added and cannot be excluded (will be added anyway).
**Arguments**:
- `alias (str)`: relation prefix
- `excludable (ExcludableItems)`: structure of fields to include and exclude
- `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**:
@ -183,7 +107,7 @@ exclusion, for nested models all related models are excluded.
```python
| @classmethod
| get_names_to_exclude(cls, fields: Optional[Union[Dict, Set]] = None, exclude_fields: Optional[Union[Dict, Set]] = None) -> Set
| get_names_to_exclude(cls, excludable: ExcludableItems, alias: str) -> Set
```
Returns a set of models field names that should be explicitly excluded
@ -197,8 +121,8 @@ 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
- `alias (str)`: alias of current relation
- `excludable (ExcludableItems)`: structure of fields to include and exclude
**Returns**:

View File

@ -40,12 +40,26 @@ List is cached in cls._related_fields for quicker access.
`(List)`: list of related fields
<a name="models.mixins.relation_mixin.RelationMixin.extract_through_names"></a>
#### extract\_through\_names
```python
| @classmethod
| extract_through_names(cls) -> Set
```
Extracts related fields through names which are shortcuts to through models.
**Returns**:
`(Set)`: set of related through fields names
<a name="models.mixins.relation_mixin.RelationMixin.extract_related_names"></a>
#### extract\_related\_names
```python
| @classmethod
| extract_related_names(cls) -> Set
| extract_related_names(cls) -> Set[str]
```
Returns List of fields names for all relations declared on a model.
@ -53,7 +67,7 @@ List is cached in cls._related_names for quicker access.
**Returns**:
`(List)`: list of related fields names
`(Set)`: set of related fields names
<a name="models.mixins.relation_mixin.RelationMixin._extract_db_related_names"></a>
#### \_extract\_db\_related\_names
@ -91,3 +105,24 @@ for nested models all related models are returned.
`(Set)`: set of non mandatory related fields
<a name="models.mixins.relation_mixin.RelationMixin._iterate_related_models"></a>
#### \_iterate\_related\_models
```python
| @classmethod
| _iterate_related_models(cls, visited: Set[Union[Type["Model"], Type["RelationMixin"]]] = None, source_relation: str = None, source_model: Union[Type["Model"], Type["RelationMixin"]] = None) -> List[str]
```
Iterates related models recursively to extract relation strings of
nested not visited models.
**Arguments**:
- `visited (Set[str])`: set of already visited models
- `source_relation (str)`: name of the current relation
- `source_model (Type["Model"])`: model from which relation comes in nested relations
**Returns**:
`(List[str])`: list of relation strings to be passed to select_related

View File

@ -91,3 +91,22 @@ passed by the user.
`(Dict)`: dictionary of model that is about to be saved
<a name="models.mixins.save_mixin.SavePrepareMixin.validate_choices"></a>
#### validate\_choices
```python
| @classmethod
| validate_choices(cls, new_kwargs: Dict) -> Dict
```
Receives dictionary of model that is about to be saved and validates the
fields with choices set to see if the value is allowed.
**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

@ -12,61 +12,6 @@ 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.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
@ -87,26 +32,6 @@ All properties here are used as "cache" to not recalculate them constantly.
- `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
@ -141,24 +66,6 @@ Signals are emitted in both model own methods and in selected queryset ones.
- `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)`: related 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
@ -195,7 +102,7 @@ Updates Meta parameters in child from parent if needed.
#### copy\_and\_replace\_m2m\_through\_model
```python
copy_and_replace_m2m_through_model(field: Type[ManyToManyField], field_name: str, table_name: str, parent_fields: Dict, attrs: Dict, meta: ModelMeta) -> None
copy_and_replace_m2m_through_model(field: Type[ManyToManyField], field_name: str, table_name: str, parent_fields: Dict, attrs: Dict, meta: ModelMeta, base_class: Type["Model"]) -> None
```
Clones class with Through model for m2m relations, appends child name to the name
@ -211,6 +118,7 @@ Removes the original sqlalchemy table from metadata if it was not removed.
**Arguments**:
- `base_class (Type["Model"])`: base class model
- `field (Type[ManyToManyField])`: field with relations definition
- `field_name (str)`: name of the relation field
- `table_name (str)`: name of the table
@ -281,6 +189,24 @@ If the class is a ormar.Model it is skipped.
`(Tuple[Dict, Dict])`: updated attrs and model_fields
<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)`: related 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.ModelMetaclass"></a>
## ModelMetaclass Objects

View File

@ -0,0 +1,132 @@
<a name="models.model_row"></a>
# models.model\_row
<a name="models.model_row.ModelRow"></a>
## ModelRow Objects
```python
class ModelRow(NewBaseModel)
```
<a name="models.model_row.ModelRow.from_row"></a>
#### from\_row
```python
| @classmethod
| from_row(cls, row: sqlalchemy.engine.ResultProxy, source_model: Type["Model"], select_related: List = None, related_models: Any = None, related_field: Type["ForeignKeyField"] = None, excludable: ExcludableItems = None, current_relation_str: str = "", proxy_source_model: Optional[Type["Model"]] = None) -> Optional["Model"]
```
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**:
- `proxy_source_model (Optional[Type["ModelRow"]])`: source model from which querysetproxy is constructed
- `excludable (ExcludableItems)`: structure of fields to include and exclude
- `current_relation_str (str)`: name of the relation field
- `source_model (Type[Model])`: model on which relation was defined
- `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
- `related_field (Type[ForeignKeyField])`: field with relation declaration
**Returns**:
`(Optional[Model])`: returns model if model is populated from database
<a name="models.model_row.ModelRow._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, source_model: Type["Model"], related_models: Any, excludable: ExcludableItems, table_prefix: str, current_relation_str: str = None, proxy_source_model: Type["Model"] = 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**:
- `proxy_source_model (Optional[Type["ModelRow"]])`: source model from which querysetproxy is constructed
- `excludable (ExcludableItems)`: structure of fields to include and exclude
- `source_model (Type[Model])`: source model from which relation started
- `current_relation_str (str)`: joined related parts into one string
- `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
**Returns**:
`(Dict)`: dictionary with keys corresponding to model fields names
and values are database values
<a name="models.model_row.ModelRow.populate_through_instance"></a>
#### populate\_through\_instance
```python
| @classmethod
| populate_through_instance(cls, row: sqlalchemy.engine.ResultProxy, through_name: str, related: str, excludable: ExcludableItems) -> "ModelRow"
```
Initialize the through model from db row.
Excluded all relation fields and other exclude/include set in excludable.
**Arguments**:
- `row (sqlalchemy.engine.ResultProxy)`: loaded row from database
- `through_name (str)`: name of the through field
- `related (str)`: name of the relation
- `excludable (ExcludableItems)`: structure of fields to include and exclude
**Returns**:
`("ModelRow")`: initialized through model without relation
<a name="models.model_row.ModelRow.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, excludable: ExcludableItems) -> 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 related dict later used to construct a Model.
Used in Model.from_row and PrefetchQuery._populate_rows methods.
**Arguments**:
- `excludable (ExcludableItems)`: structure of fields to include and exclude
- `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.
**Returns**:
`(Dict)`: dictionary with keys corresponding to model fields names
and values are database values

View File

@ -5,122 +5,14 @@
## Model Objects
```python
class Model(NewBaseModel)
class Model(ModelRow)
```
<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, source_model: Type[T] = None, related_name: str = None, fields: Optional[Union[Dict, Set]] = None, exclude_fields: Optional[Union[Dict, Set]] = None, current_relation_str: str = 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**:
- `current_relation_str (str)`: name of the relation field
- `source_model (Type[Model])`: model on which relation was defined
- `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, current_relation_str: str = None, source_model: Type[T] = 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**:
- `source_model (Type[Model])`: source model from which relation started
- `current_relation_str (str)`: joined related parts into one string
- `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 related 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
| async upsert(**kwargs: Any) -> "Model"
```
Performs either a save or an update depending on the presence of the pk.
@ -139,7 +31,7 @@ For save kwargs are ignored, used only in update if provided.
#### save
```python
| async save() -> T
| async save() -> "Model"
```
Performs a save of given Model instance.
@ -203,7 +95,7 @@ number of updated instances
```python
| @staticmethod
| async _update_and_follow(rel: T, follow: bool, visited: Set, update_count: int) -> Tuple[int, Set]
| async _update_and_follow(rel: "Model", follow: bool, visited: Set, update_count: int) -> Tuple[int, Set]
```
Internal method used in save_related to follow related models and update numbers
@ -227,7 +119,7 @@ number of updated instances
#### update
```python
| async update(**kwargs: Any) -> T
| async update(**kwargs: Any) -> "Model"
```
Performs update of Model instance in the database.
@ -274,7 +166,7 @@ or update and the Model will be saved in database again.
#### load
```python
| async load() -> T
| async load() -> "Model"
```
Allow to refresh existing Models fields from database.
@ -289,3 +181,40 @@ Does NOT refresh the related models fields if they were loaded before.
`(Model)`: reloaded Model
<a name="models.model.Model.load_all"></a>
#### load\_all
```python
| async load_all(follow: bool = False, exclude: Union[List, str, Set, Dict] = None) -> "Model"
```
Allow to refresh existing Models fields from database.
Performs refresh of the related models fields.
By default loads only self and the directly related ones.
If follow=True is set it loads 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 loaded, but the load do not
follow them inside. So Model A -> Model B -> Model C -> Model A -> Model X
will load second Model A but will never follow into Model X.
Nested relations of those kind need to be loaded manually.
**Raises**:
- `NoMatch`: If given pk is not found in database.
**Arguments**:
- `exclude ()`:
- `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
**Returns**:
`(Model)`: reloaded Model

View File

@ -146,7 +146,7 @@ Raises exception if model is abstract or has ForwardRefs in relation fields.
#### \_extract\_related\_model\_instead\_of\_field
```python
| _extract_related_model_instead_of_field(item: str) -> Optional[Union["T", Sequence["T"]]]
| _extract_related_model_instead_of_field(item: str) -> Optional[Union["Model", Sequence["Model"]]]
```
Retrieves the related model/models from RelationshipManager.
@ -276,7 +276,7 @@ cause some dialect require different treatment
#### remove
```python
| remove(parent: "T", name: str) -> None
| remove(parent: "Model", name: str) -> None
```
Removes child from relation with given name in RelationshipManager

View File

@ -22,11 +22,25 @@ Shortcut for ormar's model AliasManager stored on Meta.
`(AliasManager)`: alias manager from model's Meta
<a name="queryset.join.SqlJoin.on_clause"></a>
#### on\_clause
<a name="queryset.join.SqlJoin.to_table"></a>
#### to\_table
```python
| on_clause(previous_alias: str, from_clause: str, to_clause: str) -> text
| @property
| to_table() -> str
```
Shortcut to table name of the next model
**Returns**:
`(str)`: name of the target table
<a name="queryset.join.SqlJoin._on_clause"></a>
#### \_on\_clause
```python
| _on_clause(previous_alias: str, from_clause: str, to_clause: str) -> text
```
Receives aliases and names of both ends of the join and combines them
@ -99,11 +113,11 @@ Updated are:
- `related_name (str)`: name of the relation to follow
- `remainder (Any)`: deeper tables if there are more nested joins
<a name="queryset.join.SqlJoin.process_m2m_through_table"></a>
#### process\_m2m\_through\_table
<a name="queryset.join.SqlJoin._process_m2m_through_table"></a>
#### \_process\_m2m\_through\_table
```python
| process_m2m_through_table() -> None
| _process_m2m_through_table() -> None
```
Process Through table of the ManyToMany relation so that source table is
@ -119,11 +133,11 @@ Replaces needed parameters like:
To point to through model
<a name="queryset.join.SqlJoin.process_m2m_related_name_change"></a>
#### process\_m2m\_related\_name\_change
<a name="queryset.join.SqlJoin._process_m2m_related_name_change"></a>
#### \_process\_m2m\_related\_name\_change
```python
| process_m2m_related_name_change(reverse: bool = False) -> str
| _process_m2m_related_name_change(reverse: bool = False) -> str
```
Extracts relation name to link join through the Through model declared on
@ -158,74 +172,21 @@ Updates the used aliases list directly.
Process order_by causes for non m2m relations.
<a name="queryset.join.SqlJoin._replace_many_to_many_order_by_columns"></a>
#### \_replace\_many\_to\_many\_order\_by\_columns
<a name="queryset.join.SqlJoin._get_order_bys"></a>
#### \_get\_order\_bys
```python
| _replace_many_to_many_order_by_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], to_table: str) -> 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 '__'
- `to_table (sqlalchemy.sql.elements.quoted_name)`: target table
<a name="queryset.join.SqlJoin.get_order_bys"></a>
#### get\_order\_bys
```python
| get_order_bys(to_table: str, pkname_alias: str) -> None
| _get_order_bys() -> None
```
Triggers construction of order bys if they are given.
Otherwise by default each table is sorted by a primary key column asc.
**Arguments**:
- `to_table (sqlalchemy.sql.elements.quoted_name)`: target table
- `pkname_alias (str)`: alias of the primary key column
<a name="queryset.join.SqlJoin.get_to_and_from_keys"></a>
#### get\_to\_and\_from\_keys
<a name="queryset.join.SqlJoin._get_to_and_from_keys"></a>
#### \_get\_to\_and\_from\_keys
```python
| get_to_and_from_keys() -> Tuple[str, str]
| _get_to_and_from_keys() -> Tuple[str, str]
```
Based on the relation type, name of the relation and previous models and parts

View File

@ -1,26 +1,6 @@
<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
@ -232,7 +212,7 @@ on each of the parent models from list.
#### \_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
| async _extract_related_models(related: str, target_model: Type["Model"], prefetch_dict: Dict, select_dict: Dict, excludable: "ExcludableItems", orders_by: Dict) -> None
```
Constructs queries with required ids and extracts data with fields that should
@ -261,7 +241,7 @@ Calls itself recurrently to extract deeper nested relations of related model.
#### \_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]
| async _run_prefetch_query(target_field: Type["BaseField"], excludable: "ExcludableItems", filter_clauses: List, related_field_name: str) -> Tuple[str, str, List]
```
Actually runs the queries against the database and populates the raw response
@ -273,8 +253,6 @@ 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**:
@ -320,7 +298,7 @@ Updates models that are already loaded, usually children of children.
#### \_populate\_rows
```python
| _populate_rows(rows: List, target_field: Type["ForeignKeyField"], 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
| _populate_rows(rows: List, target_field: Type["ForeignKeyField"], parent_model: Type["Model"], table_prefix: str, exclude_prefix: str, excludable: "ExcludableItems", prefetch_dict: Dict, orders_by: Dict) -> None
```
Instantiates children models extracted from given relation.
@ -334,12 +312,11 @@ and set on the parent model after sorting if needed.
**Arguments**:
- `excludable (ExcludableItems)`: structure of fields to include and exclude
- `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

@ -38,6 +38,16 @@ Shortcut to model class set on QuerySet.
`(Type[Model])`: model class
<a name="queryset.queryset.QuerySet.rebuild_self"></a>
#### rebuild\_self
```python
| rebuild_self(filter_clauses: List = None, exclude_clauses: List = None, select_related: List = None, limit_count: int = None, offset: int = None, excludable: "ExcludableItems" = None, order_bys: List = None, prefetch_related: List = None, limit_raw_sql: bool = None, proxy_source_model: Optional[Type["Model"]] = None) -> "QuerySet"
```
Method that returns new instance of queryset based on passed params,
all not passed params are taken from current values.
<a name="queryset.queryset.QuerySet._prefetch_related_models"></a>
#### \_prefetch\_related\_models
@ -252,7 +262,7 @@ To chain related `Models` relation use double underscores between names.
#### fields
```python
| fields(columns: Union[List, str, Set, Dict]) -> "QuerySet"
| fields(columns: Union[List, str, Set, Dict], _is_exclude: bool = False) -> "QuerySet"
```
With `fields()` you can select subset of model columns to limit the data load.
@ -293,6 +303,7 @@ To include whole nested model specify model related field name and ellipsis.
**Arguments**:
- `_is_exclude (bool)`: flag if it's exclude or include operation
- `columns (Union[List, str, Set, Dict])`: columns to include
**Returns**:

View File

@ -17,38 +17,6 @@ class Query()
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

View File

@ -154,7 +154,7 @@ with all children models under their relation keys.
#### get\_relationship\_alias\_model\_and\_str
```python
get_relationship_alias_model_and_str(source_model: Type["Model"], related_parts: List) -> Tuple[str, Type["Model"], str]
get_relationship_alias_model_and_str(source_model: Type["Model"], related_parts: List) -> Tuple[str, Type["Model"], str, bool]
```
Walks the relation to retrieve the actual model on which the clause should be

View File

@ -120,7 +120,7 @@ Adds alias to the dictionary of aliases under given key.
#### resolve\_relation\_alias
```python
| resolve_relation_alias(from_model: Type["Model"], relation_name: str) -> str
| resolve_relation_alias(from_model: Union[Type["Model"], Type["ModelRow"]], relation_name: str) -> str
```
Given model and relation name returns the alias for this relation.
@ -134,3 +134,24 @@ Given model and relation name returns the alias for this relation.
`(str)`: alias of the relation
<a name="relations.alias_manager.AliasManager.resolve_relation_alias_after_complex"></a>
#### resolve\_relation\_alias\_after\_complex
```python
| resolve_relation_alias_after_complex(source_model: Union[Type["Model"], Type["ModelRow"]], relation_str: str, relation_field: Type["ForeignKeyField"]) -> str
```
Given source model and relation string returns the alias for this complex
relation if it exists, otherwise fallback to normal relation from a relation
field definition.
**Arguments**:
- `relation_field (Type["ForeignKeyField"])`: field with direct relation definition
- `source_model (source Model)`: model with query starts
- `relation_str (str)`: string with relation joins defined
**Returns**:
`(str)`: alias of the relation

View File

@ -5,7 +5,7 @@
## QuerysetProxy Objects
```python
class QuerysetProxy(ormar.QuerySetProtocol)
class QuerysetProxy()
```
Exposes QuerySet methods on relations, but also handles creating and removing
@ -43,7 +43,7 @@ Set's the queryset. Initialized in RelationProxy.
#### \_assign\_child\_to\_parent
```python
| _assign_child_to_parent(child: Optional["T"]) -> None
| _assign_child_to_parent(child: Optional["Model"]) -> None
```
Registers child in parents RelationManager.
@ -56,7 +56,7 @@ Registers child in parents RelationManager.
#### \_register\_related
```python
| _register_related(child: Union["T", Sequence[Optional["T"]]]) -> None
| _register_related(child: Union["Model", Sequence[Optional["Model"]]]) -> None
```
Registers child/ children in parents RelationManager.
@ -78,20 +78,35 @@ Cleans the current list of the related models.
#### create\_through\_instance
```python
| async create_through_instance(child: "T") -> None
| async create_through_instance(child: "Model", **kwargs: Any) -> None
```
Crete a through model instance in the database for m2m relations.
**Arguments**:
- `kwargs (Any)`: dict of additional keyword arguments for through instance
- `child (Model)`: child model instance
<a name="relations.querysetproxy.QuerysetProxy.update_through_instance"></a>
#### update\_through\_instance
```python
| async update_through_instance(child: "Model", **kwargs: Any) -> None
```
Updates a through model instance in the database for m2m relations.
**Arguments**:
- `kwargs (Any)`: dict of additional keyword arguments for through instance
- `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
| async delete_through_instance(child: "Model") -> None
```
Removes through model instance from the database for m2m relations.
@ -256,6 +271,27 @@ Actual call delegated to QuerySet.
`(Model)`: created model
<a name="relations.querysetproxy.QuerysetProxy.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="relations.querysetproxy.QuerysetProxy.get_or_create"></a>
#### get\_or\_create

View File

@ -10,37 +10,6 @@ class RelationsManager()
Manages relations on a Model, each Model has it's own instance.
<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\_\_
@ -62,7 +31,7 @@ Checks if relation with given name is already registered.
#### get
```python
| get(name: str) -> Optional[Union["T", Sequence["T"]]]
| get(name: str) -> Optional[Union["Model", Sequence["Model"]]]
```
Returns the related model/models if relation is set.
@ -76,23 +45,6 @@ Actual call is delegated to Relation instance registered under relation name.
`(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
@ -148,3 +100,51 @@ of relation from which you want to remove the parent.
- `parent (Model)`: parent Model
- `name (str)`: name of the relation
<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._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

View File

@ -131,7 +131,7 @@ will be deleted, and not only removed from relation).
#### add
```python
| async add(item: "Model") -> None
| async add(item: "Model", **kwargs: Any) -> None
```
Adds child model to relation.
@ -140,5 +140,6 @@ For ManyToMany relations through instance is automatically created.
**Arguments**:
- `kwargs (Any)`: dict of additional keyword arguments for through instance
- `item (Model)`: child to add to relation

View File

@ -27,7 +27,7 @@ Keeps related Models and handles adding/removing of the children.
#### \_\_init\_\_
```python
| __init__(manager: "RelationsManager", type_: RelationType, field_name: str, to: Type["T"], through: Type["T"] = None) -> None
| __init__(manager: "RelationsManager", type_: RelationType, field_name: str, to: Type["Model"], through: Type["Model"] = None) -> None
```
Initialize the Relation and keep the related models either as instances of
@ -73,7 +73,7 @@ Find child model in RelationProxy if exists.
#### add
```python
| add(child: "T") -> None
| add(child: "Model") -> None
```
Adds child Model to relation, either sets child as related model or adds
@ -101,7 +101,7 @@ it from the list in RelationProxy depending on relation type.
#### get
```python
| get() -> Optional[Union[List["T"], "T"]]
| get() -> Optional[Union[List["Model"], "Model"]]
```
Return the related model or models from RelationProxy.