Skip to content

queryset.prefetch_query

sort_models

1
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 of models already fetched from db :type models: List[tests.test_prefetch_related.Division]
  • orders_by: order by dictionary :type orders_by: Dict[str, str]

Returns:

sorted list of models :rtype: List[tests.test_prefetch_related.Division]

set_children_on_model

1
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: parent model instance :type model: Model
  • related: name of the related field :type related: str
  • children: dictionary of children ids/ related field value :type children: Dict[int, set]
  • model_id: id of the model on which children should be set :type model_id: int
  • models: dictionary of child models instances :type models: Dict
  • orders_by: order_by dictionary :type orders_by: Dict

PrefetchQuery Objects

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

1
 | 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 of already instantiated models from main query :type models: List[Model]
  • rows: row sql result of the main query before the prefetch :type rows: List[sqlalchemy.engine.result.RowProxy]

Returns:

list of models with children prefetched :rtype: List[Model]

_extract_ids_from_raw_data

1
 | _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: ormar model class :type parent_model: Type[Model]
  • column_name: name of the relation column which is a key column :type column_name: str

Returns:

set of ids of related model that should be extracted :rtype: set

_extract_ids_from_preloaded_models

1
 | _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: model from which related ids should be extracted :type parent_model: Type["Model"]
  • column_name: name of the relation column which is a key column :type column_name: str

Returns:

set of ids of related model that should be extracted :rtype: set

_extract_required_ids

1
 | _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: model from which related ids should be extracted :type parent_model: Type["Model"]
  • reverse: flag if the relation is reverse :type reverse: bool
  • related: name of the field with relation :type related: str

Returns:

set of ids of related model that should be extracted :rtype: set

_get_filter_for_prefetch

1
 | _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: model from which related ids should be extracted :type parent_model: Type["Model"]
  • target_model: model to which relation leads to :type target_model: Type["Model"]
  • reverse: flag if the relation is reverse :type reverse: bool
  • related: name of the field with relation :type related: str

Returns:

:rtype: List[sqlalchemy.sql.elements.TextClause]

1
 | _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: ormar model instance :type model: Model
  • prefetch_dict: dictionary of models to prefetch :type prefetch_dict: Dict
  • orders_by: dictionary of order bys :type orders_by: Dict

Returns:

model with children populated :rtype: Model

1
 | 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 of parent models from main query :type models: List[Model]
  • rows: raw response from sql query :type rows: List[sqlalchemy.engine.result.RowProxy]

Returns:

list of models with prefetch children populated :rtype: List[Model]

1
 | 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 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: name of the relation :type related: str
  • target_model: model to which relation leads to :type target_model: Type[Model]
  • prefetch_dict: prefetch related list converted into dictionary :type prefetch_dict: Dict
  • select_dict: select related list converted into dictionary :type select_dict: Dict
  • fields: fields to include :type fields: Union[Set[Any], Dict[Any, Any], None]
  • exclude_fields: fields to exclude :type exclude_fields: Union[Set[Any], Dict[Any, Any], None]
  • orders_by: dictionary of order bys clauses :type orders_by: Dict

Returns:

None :rtype: None

_run_prefetch_query

1
 | async _run_prefetch_query(target_field: "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 for given related model.

Returns table prefix as it's later needed to eventually initialize the children models.

Arguments:

  • target_field: ormar field with relation definition :type target_field: "BaseField"
  • filter_clauses: list of clauses, actually one clause with ids of relation :type filter_clauses: List[sqlalchemy.sql.elements.TextClause]

Returns:

table prefix and raw rows from sql response :rtype: Tuple[str, List]

1
2
 | @staticmethod
 | _get_select_related_if_apply(related: str, select_dict: Dict) -> Dict

Extract nested related of select_related dictionary to extract models nested deeper on related model and already loaded in select related query.

Arguments:

  • related: name of the relation :type related: str
  • select_dict: dictionary of select related models in main query :type select_dict: Dict

Returns:

dictionary with nested related of select related :rtype: Dict

_update_already_loaded_rows

1
 | _update_already_loaded_rows(target_field: "BaseField", prefetch_dict: Dict, orders_by: Dict) -> None

Updates models that are already loaded, usually children of children.

Arguments:

  • target_field: ormar field with relation definition :type target_field: "BaseField"
  • prefetch_dict: dictionaries of related models to prefetch :type prefetch_dict: Dict
  • orders_by: dictionary of order by clauses by model :type orders_by: Dict

_populate_rows

1
 | _populate_rows(rows: List, target_field: "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.

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:

  • excludable: structure of fields to include and exclude :type excludable: ExcludableItems
  • rows: raw sql response from the prefetch query :type rows: List[sqlalchemy.engine.result.RowProxy]
  • target_field: field with relation definition from parent model :type target_field: "BaseField"
  • parent_model: model with relation definition :type parent_model: Type[Model]
  • table_prefix: prefix of the target table from current relation :type table_prefix: str
  • prefetch_dict: dictionaries of related models to prefetch :type prefetch_dict: Dict
  • orders_by: dictionary of order by clauses by model :type orders_by: Dict