Bases: QueryAction
Order Actions is populated by queryset when order_by() is called.
All required params are extracted but kept raw until actual filter clause value
is required -> then the action is converted into text() clause.
Extracted in order to easily change table prefixes on complex relations.
Source code in ormar\queryset\actions\order_action.py
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 | class OrderAction(QueryAction):
"""
Order Actions is populated by queryset when order_by() is called.
All required params are extracted but kept raw until actual filter clause value
is required -> then the action is converted into text() clause.
Extracted in order to easily change table prefixes on complex relations.
"""
def __init__(
self, order_str: str, model_cls: Type["Model"], alias: Optional[str] = None
) -> None:
self.direction: str = ""
super().__init__(query_str=order_str, model_cls=model_cls)
self.is_source_model_order = False
if alias:
self.table_prefix = alias
if self.source_model == self.target_model and "__" not in self.related_str:
self.is_source_model_order = True
@property
def field_alias(self) -> str:
return self.target_model.get_column_alias(self.field_name)
@property
def is_postgres_bool(self) -> bool:
dialect = self.target_model.ormar_config.database._backend._dialect.name
field_type = self.target_model.ormar_config.model_fields[
self.field_name
].__type__
return dialect == "postgresql" and field_type == bool
def get_field_name_text(self) -> str:
"""
Escapes characters if it's required.
Substitutes values of the models if value is a ormar Model with its pk value.
Compiles the clause.
:return: complied and escaped clause
:rtype: sqlalchemy.sql.elements.TextClause
"""
prefix = f"{self.table_prefix}_" if self.table_prefix else ""
return f"{prefix}{self.table}" f".{self.field_alias}"
def get_min_or_max(self) -> sqlalchemy.sql.expression.TextClause:
"""
Used in limit sub queries where you need to use aggregated functions
in order to order by columns not included in group by. For postgres bool
field it's using bool_or function as aggregates does not work with this type
of columns.
:return: min or max function to order
:rtype: sqlalchemy.sql.elements.TextClause
"""
prefix = f"{self.table_prefix}_" if self.table_prefix else ""
if self.direction == "":
function = "min" if not self.is_postgres_bool else "bool_or"
return text(f"{function}({prefix}{self.table}" f".{self.field_alias})")
function = "max" if not self.is_postgres_bool else "bool_or"
return text(f"{function}({prefix}{self.table}" f".{self.field_alias}) desc")
def get_text_clause(self) -> 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.
:return: complied and escaped clause
:rtype: sqlalchemy.sql.elements.TextClause
"""
dialect = self.target_model.ormar_config.database._backend._dialect
quoter = dialect.identifier_preparer.quote
prefix = f"{self.table_prefix}_" if self.table_prefix else ""
table_name = self.table.name
field_name = self.field_alias
if not prefix:
table_name = quoter(table_name)
else:
table_name = quoter(f"{prefix}{table_name}")
field_name = quoter(field_name)
return text(f"{table_name}.{field_name} {self.direction}")
def _split_value_into_parts(self, order_str: str) -> None:
if order_str.startswith("-"):
self.direction = "desc"
order_str = order_str[1:]
parts = order_str.split("__")
self.field_name = parts[-1]
self.related_parts = parts[:-1]
def check_if_filter_apply(self, target_model: Type["Model"], alias: str) -> bool:
"""
Checks filter conditions to find if they apply to current join.
:param target_model: model which is now processed
:type target_model: Type["Model"]
:param alias: prefix of the relation
:type alias: str
:return: result of the check
:rtype: bool
"""
return target_model == self.target_model and alias == self.table_prefix
|
check_if_filter_apply(target_model, alias)
Checks filter conditions to find if they apply to current join.
Parameters:
Name |
Type |
Description |
Default |
target_model |
Type[Model]
|
model which is now processed
|
required
|
alias |
str
|
|
required
|
Returns:
Source code in ormar\queryset\actions\order_action.py
103
104
105
106
107
108
109
110
111
112
113
114 | def check_if_filter_apply(self, target_model: Type["Model"], alias: str) -> bool:
"""
Checks filter conditions to find if they apply to current join.
:param target_model: model which is now processed
:type target_model: Type["Model"]
:param alias: prefix of the relation
:type alias: str
:return: result of the check
:rtype: bool
"""
return target_model == self.target_model and alias == self.table_prefix
|
get_field_name_text()
Escapes characters if it's required.
Substitutes values of the models if value is a ormar Model with its pk value.
Compiles the clause.
Returns:
Type |
Description |
sqlalchemy.sql.elements.TextClause
|
complied and escaped clause
|
Source code in ormar\queryset\actions\order_action.py
45
46
47
48
49
50
51
52
53
54
55 | def get_field_name_text(self) -> str:
"""
Escapes characters if it's required.
Substitutes values of the models if value is a ormar Model with its pk value.
Compiles the clause.
:return: complied and escaped clause
:rtype: sqlalchemy.sql.elements.TextClause
"""
prefix = f"{self.table_prefix}_" if self.table_prefix else ""
return f"{prefix}{self.table}" f".{self.field_alias}"
|
get_min_or_max()
Used in limit sub queries where you need to use aggregated functions
in order to order by columns not included in group by. For postgres bool
field it's using bool_or function as aggregates does not work with this type
of columns.
Returns:
Type |
Description |
sqlalchemy.sql.elements.TextClause
|
min or max function to order
|
Source code in ormar\queryset\actions\order_action.py
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 | def get_min_or_max(self) -> sqlalchemy.sql.expression.TextClause:
"""
Used in limit sub queries where you need to use aggregated functions
in order to order by columns not included in group by. For postgres bool
field it's using bool_or function as aggregates does not work with this type
of columns.
:return: min or max function to order
:rtype: sqlalchemy.sql.elements.TextClause
"""
prefix = f"{self.table_prefix}_" if self.table_prefix else ""
if self.direction == "":
function = "min" if not self.is_postgres_bool else "bool_or"
return text(f"{function}({prefix}{self.table}" f".{self.field_alias})")
function = "max" if not self.is_postgres_bool else "bool_or"
return text(f"{function}({prefix}{self.table}" f".{self.field_alias}) desc")
|
get_text_clause()
Escapes characters if it's required.
Substitutes values of the models if value is a ormar Model with its pk value.
Compiles the clause.
Returns:
Type |
Description |
sqlalchemy.sql.elements.TextClause
|
complied and escaped clause
|
Source code in ormar\queryset\actions\order_action.py
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 | def get_text_clause(self) -> 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.
:return: complied and escaped clause
:rtype: sqlalchemy.sql.elements.TextClause
"""
dialect = self.target_model.ormar_config.database._backend._dialect
quoter = dialect.identifier_preparer.quote
prefix = f"{self.table_prefix}_" if self.table_prefix else ""
table_name = self.table.name
field_name = self.field_alias
if not prefix:
table_name = quoter(table_name)
else:
table_name = quoter(f"{prefix}{table_name}")
field_name = quoter(field_name)
return text(f"{table_name}.{field_name} {self.direction}")
|