Skip to content

prefetch_mixin

PrefetchQueryMixin

Bases: RelationMixin

Used in PrefetchQuery to extract ids and names of models to prefetch.

Source code in ormar/models/mixins/prefetch_mixin.py
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
class PrefetchQueryMixin(RelationMixin):
    """
    Used in PrefetchQuery to extract ids and names of models to prefetch.
    """

    if TYPE_CHECKING:  # pragma no cover
        from ormar import Model

        get_name: Callable  # defined in NewBaseModel

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

        :param parent_model: related model that the relation lead to
        :type parent_model: Type[Model]
        :param target_model: model on which query should be perfomed
        :type target_model: Type[Model]
        :param reverse: flag if the relation is reverse
        :type reverse: bool
        :param related: name of the relation field
        :type related: str
        :return: Model on which query clause should be performed and name of the column
        :rtype: Tuple[Type[Model], str]
        """
        if reverse:
            field_name = parent_model.Meta.model_fields[related].get_related_name()
            field = target_model.Meta.model_fields[field_name]
            if field.is_multi:
                field = cast("ManyToManyField", field)
                field_name = field.default_target_field_name()
                sub_field = field.through.Meta.model_fields[field_name]
                return field.through, sub_field.get_alias()
            return target_model, field.get_alias()
        target_field = target_model.get_column_alias(target_model.Meta.pkname)
        return target_model, target_field

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

        :param parent_model: model from which id column should be extracted
        :type parent_model: Type[Model]
        :param reverse: flag if the relation is reverse
        :type reverse: bool
        :param related: name of the relation field
        :type related: str
        :param use_raw: flag if aliases or field names should be used
        :type use_raw: bool
        :return:
        :rtype:
        """
        if reverse:
            column_name = parent_model.Meta.pkname
            return (
                parent_model.get_column_alias(column_name) if use_raw else column_name
            )
        column = parent_model.Meta.model_fields[related]
        return column.get_alias() if use_raw else column.name

    @classmethod
    def get_related_field_name(cls, target_field: "ForeignKeyField") -> 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.

        :param target_field: relation field that should be used in prefetch
        :type target_field: Type[BaseField]
        :return: name of the field
        :rtype: str
        """
        if target_field.is_multi:
            return cls.get_name()
        if target_field.virtual:
            return target_field.get_related_name()
        return target_field.to.Meta.pkname

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

        :param prefetch_dict: dictionary of fields to extract
        :type prefetch_dict: Dict
        :return: list of fields names to extract
        :rtype: List
        """
        related_to_extract = []
        if prefetch_dict and prefetch_dict is not Ellipsis:
            related_to_extract = [
                related
                for related in cls.extract_related_names()
                if related in prefetch_dict
            ]
        return related_to_extract

get_clause_target_and_filter_column_name(parent_model, target_model, reverse, related) staticmethod

Returns Model on which query clause should be performed and name of the column.

Parameters:

Name Type Description Default
parent_model Type['Model']

related model that the relation lead to

required
target_model Type['Model']

model on which query should be perfomed

required
reverse bool

flag if the relation is reverse

required
related str

name of the relation field

required

Returns:

Type Description
Tuple[Type[Model], str]

Model on which query clause should be performed and name of the column

Source code in ormar/models/mixins/prefetch_mixin.py
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@staticmethod
def 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.

    :param parent_model: related model that the relation lead to
    :type parent_model: Type[Model]
    :param target_model: model on which query should be perfomed
    :type target_model: Type[Model]
    :param reverse: flag if the relation is reverse
    :type reverse: bool
    :param related: name of the relation field
    :type related: str
    :return: Model on which query clause should be performed and name of the column
    :rtype: Tuple[Type[Model], str]
    """
    if reverse:
        field_name = parent_model.Meta.model_fields[related].get_related_name()
        field = target_model.Meta.model_fields[field_name]
        if field.is_multi:
            field = cast("ManyToManyField", field)
            field_name = field.default_target_field_name()
            sub_field = field.through.Meta.model_fields[field_name]
            return field.through, sub_field.get_alias()
        return target_model, field.get_alias()
    target_field = target_model.get_column_alias(target_model.Meta.pkname)
    return target_model, target_field

get_column_name_for_id_extraction(parent_model, reverse, related, use_raw) staticmethod

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.

Parameters:

Name Type Description Default
parent_model Type['Model']

model from which id column should be extracted

required
reverse bool

flag if the relation is reverse

required
related str

name of the relation field

required
use_raw bool

flag if aliases or field names should be used

required

Returns:

Type Description
Source code in ormar/models/mixins/prefetch_mixin.py
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
@staticmethod
def 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.

    :param parent_model: model from which id column should be extracted
    :type parent_model: Type[Model]
    :param reverse: flag if the relation is reverse
    :type reverse: bool
    :param related: name of the relation field
    :type related: str
    :param use_raw: flag if aliases or field names should be used
    :type use_raw: bool
    :return:
    :rtype:
    """
    if reverse:
        column_name = parent_model.Meta.pkname
        return (
            parent_model.get_column_alias(column_name) if use_raw else column_name
        )
    column = parent_model.Meta.model_fields[related]
    return column.get_alias() if use_raw else column.name

get_filtered_names_to_extract(prefetch_dict) classmethod

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.

Parameters:

Name Type Description Default
prefetch_dict Dict

dictionary of fields to extract

required

Returns:

Type Description
List

list of fields names to extract

Source code in ormar/models/mixins/prefetch_mixin.py
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
@classmethod
def 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.

    :param prefetch_dict: dictionary of fields to extract
    :type prefetch_dict: Dict
    :return: list of fields names to extract
    :rtype: List
    """
    related_to_extract = []
    if prefetch_dict and prefetch_dict is not Ellipsis:
        related_to_extract = [
            related
            for related in cls.extract_related_names()
            if related in prefetch_dict
        ]
    return related_to_extract

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.

Parameters:

Name Type Description Default
target_field 'ForeignKeyField'

relation field that should be used in prefetch

required

Returns:

Type Description
str

name of the field

Source code in ormar/models/mixins/prefetch_mixin.py
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
@classmethod
def get_related_field_name(cls, target_field: "ForeignKeyField") -> 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.

    :param target_field: relation field that should be used in prefetch
    :type target_field: Type[BaseField]
    :return: name of the field
    :rtype: str
    """
    if target_field.is_multi:
        return cls.get_name()
    if target_field.virtual:
        return target_field.get_related_name()
    return target_field.to.Meta.pkname