add tests for cross model forward references, add docs for processing forwardrefs, wip on refactoring queries into separate pages based on functionality

This commit is contained in:
collerek
2021-01-26 17:29:40 +01:00
parent a2834666fc
commit b710ed9780
39 changed files with 2054 additions and 1004 deletions

View File

@ -1,6 +1,24 @@
<a name="models.helpers.models"></a>
# models.helpers.models
<a name="models.helpers.models.is_field_an_forward_ref"></a>
#### is\_field\_an\_forward\_ref
```python
is_field_an_forward_ref(field: Type["BaseField"]) -> bool
```
Checks if field is a relation field and whether any of the referenced models
are ForwardRefs that needs to be updated before proceeding.
**Arguments**:
- `field (Type[BaseField])`: model field to verify
**Returns**:
`(bool)`: result of the check
<a name="models.helpers.models.populate_default_options_values"></a>
#### populate\_default\_options\_values
@ -62,3 +80,28 @@ Also related_names have to be unique for given related model.
- `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
```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']}}
Result dictionary is sorted by length of the values and by key
**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

View File

@ -5,7 +5,7 @@
#### register\_relation\_on\_build
```python
register_relation_on_build(new_model: Type["Model"], field_name: str) -> None
register_relation_on_build(field: Type["ForeignKeyField"]) -> None
```
Registers ForeignKey relation in alias_manager to set a table_prefix.
@ -17,14 +17,13 @@ aliases for proper sql joins.
**Arguments**:
- `new_model (Model class)`: constructed model
- `field_name (str)`: name of the related field
- `field (ForeignKey class)`: relation 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
register_many_to_many_relation_on_build(field: Type[ManyToManyField]) -> None
```
Registers connection between through model and both sides of the m2m relation.
@ -38,10 +37,25 @@ 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_relationship"></a>
#### expand\_reverse\_relationship
```python
expand_reverse_relationship(model_field: Type["ForeignKeyField"]) -> None
```
If the reverse relation has not been set before it's set here.
**Arguments**:
- `model_field ()`:
**Returns**:
`(None)`: None
<a name="models.helpers.relations.expand_reverse_relationships"></a>
#### expand\_reverse\_relationships
@ -62,7 +76,7 @@ If the reverse relation has not been set before it's set here.
#### register\_reverse\_model\_fields
```python
register_reverse_model_fields(model: Type["Model"], child: Type["Model"], related_name: str, model_field: Type["ForeignKeyField"]) -> None
register_reverse_model_fields(model_field: Type["ForeignKeyField"]) -> None
```
Registers reverse ForeignKey field on related model.
@ -73,16 +87,13 @@ 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
register_relation_in_alias_manager(field: Type[ForeignKeyField]) -> None
```
Registers the relation (and reverse relation) in alias manager.
@ -95,15 +106,13 @@ 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
verify_related_name_dont_duplicate(related_name: str, model_field: Type["ForeignKeyField"]) -> None
```
Verifies whether the used related_name (regardless of the fact if user defined or
@ -117,9 +126,8 @@ model
**Arguments**:
- `child (ormar.models.metaclass.ModelMetaclass)`: related Model class
- `parent_model (ormar.models.metaclass.ModelMetaclass)`: parent Model class
- `related_name ()`:
- `model_field (relation Field)`: original relation ForeignKey field
**Returns**:
@ -129,7 +137,7 @@ model
#### reverse\_field\_not\_already\_registered
```python
reverse_field_not_already_registered(child: Type["Model"], child_model_name: str, parent_model: Type["Model"]) -> bool
reverse_field_not_already_registered(model_field: Type["ForeignKeyField"]) -> bool
```
Checks if child is already registered in parents pydantic fields.
@ -141,9 +149,7 @@ 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
- `model_field (relation Field)`: original relation ForeignKey field
**Returns**:

View File

@ -5,7 +5,7 @@
#### adjust\_through\_many\_to\_many\_model
```python
adjust_through_many_to_many_model(model: Type["Model"], child: Type["Model"], model_field: Type[ManyToManyField]) -> None
adjust_through_many_to_many_model(model_field: Type[ManyToManyField]) -> None
```
Registers m2m relation on through model.
@ -15,23 +15,22 @@ 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
create_and_append_m2m_fk(model: Type["Model"], model_field: Type[ManyToManyField], field_name: str) -> None
```
Registers sqlalchemy Column with sqlalchemy.ForeignKey leadning to the model.
Registers sqlalchemy Column with sqlalchemy.ForeignKey leading to the model.
Newly created field is added to m2m relation through model Meta columns and table.
**Arguments**:
- `field_name (str)`: name of the column to create
- `model (Model class)`: Model class to which FK should be created
- `model_field (ManyToManyField field)`: field with ManyToMany relation
@ -83,6 +82,8 @@ cannot be pydantic_only.
Append fields to columns if it's not pydantic_only,
virtual ForeignKey or ManyToMany field.
Sets `owner` on each model_field as reference to newly created Model.
**Raises**:
- `ModelDefinitionError`: if validation of related_names fail,
@ -125,6 +126,23 @@ Each model has to have pk.
`(ormar.models.metaclass.ModelMetaclass)`: Model with populated pkname and columns in Meta
<a name="models.helpers.sqlalchemy.check_for_null_type_columns_from_forward_refs"></a>
#### check\_for\_null\_type\_columns\_from\_forward\_refs
```python
check_for_null_type_columns_from_forward_refs(meta: "ModelMeta") -> bool
```
Check is any column is of NUllType() meaning it's empty column from ForwardRef
**Arguments**:
- `meta (Model class Meta)`: Meta class of the Model without sqlalchemy table constructed
**Returns**:
`(bool)`: result of the check
<a name="models.helpers.sqlalchemy.populate_meta_sqlalchemy_table_if_required"></a>
#### populate\_meta\_sqlalchemy\_table\_if\_required
@ -143,3 +161,21 @@ It populates name, metadata, columns and constraints.
`(Model class)`: class with populated Meta.table
<a name="models.helpers.sqlalchemy.update_column_definition"></a>
#### update\_column\_definition
```python
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.
**Arguments**:
- `model (Type["Model"])`: model on which columns needs to be updated
- `field (Type[ForeignKeyField])`: field with column definition that requires update
**Returns**:
`(None)`: None