Queryset mixins (#629)
* add enum field * add decorator for asyncio * fix enum typing, additional tests, add docs * add more tests * query-mixin * use dict to replace ordereddict Co-authored-by: collerek <collerek@gmail.com>
This commit is contained in:
@ -1,4 +1,3 @@
|
|||||||
import collections
|
|
||||||
import itertools
|
import itertools
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from typing import Any, Dict, List, TYPE_CHECKING, Tuple, Type
|
from typing import Any, Dict, List, TYPE_CHECKING, Tuple, Type
|
||||||
@ -145,7 +144,7 @@ def extract_annotations_and_default_vals(attrs: Dict) -> Tuple[Dict, Dict]:
|
|||||||
return attrs, model_fields
|
return attrs, model_fields
|
||||||
|
|
||||||
|
|
||||||
def group_related_list(list_: List) -> collections.OrderedDict:
|
def group_related_list(list_: List) -> Dict:
|
||||||
"""
|
"""
|
||||||
Translates the list of related strings into a dictionary.
|
Translates the list of related strings into a dictionary.
|
||||||
That way nested models are grouped to traverse them in a right order
|
That way nested models are grouped to traverse them in a right order
|
||||||
@ -174,9 +173,7 @@ def group_related_list(list_: List) -> collections.OrderedDict:
|
|||||||
result_dict[key] = group_related_list(new)
|
result_dict[key] = group_related_list(new)
|
||||||
else:
|
else:
|
||||||
result_dict.setdefault(key, []).extend(new)
|
result_dict.setdefault(key, []).extend(new)
|
||||||
return collections.OrderedDict(
|
return dict(sorted(result_dict.items(), key=lambda item: len(item[1])))
|
||||||
sorted(result_dict.items(), key=lambda item: len(item[1]))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def meta_field_not_set(model: Type["Model"], field_name: str) -> bool:
|
def meta_field_not_set(model: Type["Model"], field_name: str) -> bool:
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
from collections import OrderedDict
|
|
||||||
from typing import Dict, List, Optional, TYPE_CHECKING, cast
|
from typing import Dict, List, Optional, TYPE_CHECKING, cast
|
||||||
|
|
||||||
import ormar
|
import ormar
|
||||||
@ -32,7 +31,7 @@ class MergeModelMixin:
|
|||||||
:rtype: List["Model"]
|
:rtype: List["Model"]
|
||||||
"""
|
"""
|
||||||
merged_rows: List["Model"] = []
|
merged_rows: List["Model"] = []
|
||||||
grouped_instances: OrderedDict = OrderedDict()
|
grouped_instances: Dict = {}
|
||||||
|
|
||||||
for model in result_rows:
|
for model in result_rows:
|
||||||
grouped_instances.setdefault(model.pk, []).append(model)
|
grouped_instances.setdefault(model.pk, []).append(model)
|
||||||
|
|||||||
@ -4,10 +4,10 @@ Contains QuerySet and different Query classes to allow for constructing of sql q
|
|||||||
from ormar.queryset.actions import FilterAction, OrderAction, SelectAction
|
from ormar.queryset.actions import FilterAction, OrderAction, SelectAction
|
||||||
from ormar.queryset.clause import and_, or_
|
from ormar.queryset.clause import and_, or_
|
||||||
from ormar.queryset.field_accessor import FieldAccessor
|
from ormar.queryset.field_accessor import FieldAccessor
|
||||||
from ormar.queryset.filter_query import FilterQuery
|
from ormar.queryset.queries import FilterQuery
|
||||||
from ormar.queryset.limit_query import LimitQuery
|
from ormar.queryset.queries import LimitQuery
|
||||||
from ormar.queryset.offset_query import OffsetQuery
|
from ormar.queryset.queries import OffsetQuery
|
||||||
from ormar.queryset.order_query import OrderQuery
|
from ormar.queryset.queries import OrderQuery
|
||||||
from ormar.queryset.queryset import QuerySet
|
from ormar.queryset.queryset import QuerySet
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
from collections import OrderedDict
|
|
||||||
from typing import Any, Dict, List, Optional, TYPE_CHECKING, Tuple, Type, cast
|
from typing import Any, Dict, List, Optional, TYPE_CHECKING, Tuple, Type, cast
|
||||||
|
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
@ -22,7 +21,7 @@ class SqlJoin:
|
|||||||
columns: List[sqlalchemy.Column],
|
columns: List[sqlalchemy.Column],
|
||||||
excludable: "ExcludableItems",
|
excludable: "ExcludableItems",
|
||||||
order_columns: Optional[List["OrderAction"]],
|
order_columns: Optional[List["OrderAction"]],
|
||||||
sorted_orders: OrderedDict,
|
sorted_orders: Dict,
|
||||||
main_model: Type["Model"],
|
main_model: Type["Model"],
|
||||||
relation_name: str,
|
relation_name: str,
|
||||||
relation_str: str,
|
relation_str: str,
|
||||||
@ -118,7 +117,7 @@ class SqlJoin:
|
|||||||
|
|
||||||
return text(f"{left_part}={right_part}")
|
return text(f"{left_part}={right_part}")
|
||||||
|
|
||||||
def build_join(self) -> Tuple[List, sqlalchemy.sql.select, List, OrderedDict]:
|
def build_join(self) -> Tuple[List, sqlalchemy.sql.select, List, Dict]:
|
||||||
"""
|
"""
|
||||||
Main external access point for building a join.
|
Main external access point for building a join.
|
||||||
Splits the join definition, updates fields and exclude_fields if needed,
|
Splits the join definition, updates fields and exclude_fields if needed,
|
||||||
@ -126,7 +125,7 @@ class SqlJoin:
|
|||||||
used_aliases and sort_orders.
|
used_aliases and sort_orders.
|
||||||
|
|
||||||
:return: list of used aliases, select from, list of aliased columns, sort orders
|
:return: list of used aliases, select from, list of aliased columns, sort orders
|
||||||
:rtype: Tuple[List[str], Join, List[TextClause], collections.OrderedDict]
|
:rtype: Tuple[List[str], Join, List[TextClause], Dict]
|
||||||
"""
|
"""
|
||||||
if self.target_field.is_multi:
|
if self.target_field.is_multi:
|
||||||
self._process_m2m_through_table()
|
self._process_m2m_through_table()
|
||||||
|
|||||||
15
ormar/queryset/queries/__init__.py
Normal file
15
ormar/queryset/queries/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from ormar.queryset.queries.filter_query import FilterQuery
|
||||||
|
from ormar.queryset.queries.limit_query import LimitQuery
|
||||||
|
from ormar.queryset.queries.offset_query import OffsetQuery
|
||||||
|
from ormar.queryset.queries.order_query import OrderQuery
|
||||||
|
from ormar.queryset.queries.prefetch_query import PrefetchQuery
|
||||||
|
from ormar.queryset.queries.query import Query
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"FilterQuery",
|
||||||
|
"LimitQuery",
|
||||||
|
"OffsetQuery",
|
||||||
|
"OrderQuery",
|
||||||
|
"PrefetchQuery",
|
||||||
|
"Query",
|
||||||
|
]
|
||||||
@ -2,7 +2,7 @@ from typing import Dict, List, Sequence, Set, TYPE_CHECKING, Tuple, Type, cast
|
|||||||
|
|
||||||
import ormar
|
import ormar
|
||||||
from ormar.queryset.clause import QueryClause
|
from ormar.queryset.clause import QueryClause
|
||||||
from ormar.queryset.query import Query
|
from ormar.queryset.queries.query import Query
|
||||||
from ormar.queryset.utils import extract_models_to_dict_of_lists, translate_list_to_dict
|
from ormar.queryset.utils import extract_models_to_dict_of_lists, translate_list_to_dict
|
||||||
|
|
||||||
if TYPE_CHECKING: # pragma: no cover
|
if TYPE_CHECKING: # pragma: no cover
|
||||||
@ -1,5 +1,4 @@
|
|||||||
from collections import OrderedDict
|
from typing import Dict, List, Optional, TYPE_CHECKING, Tuple, Type, Union
|
||||||
from typing import List, Optional, TYPE_CHECKING, Tuple, Type, Union
|
|
||||||
|
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
from sqlalchemy import Table, text
|
from sqlalchemy import Table, text
|
||||||
@ -7,7 +6,7 @@ from sqlalchemy.sql import Join
|
|||||||
|
|
||||||
import ormar # noqa I100
|
import ormar # noqa I100
|
||||||
from ormar.models.helpers.models import group_related_list
|
from ormar.models.helpers.models import group_related_list
|
||||||
from ormar.queryset import FilterQuery, LimitQuery, OffsetQuery, OrderQuery
|
from ormar.queryset.queries import FilterQuery, LimitQuery, OffsetQuery, OrderQuery
|
||||||
from ormar.queryset.actions.filter_action import FilterAction
|
from ormar.queryset.actions.filter_action import FilterAction
|
||||||
from ormar.queryset.join import SqlJoin
|
from ormar.queryset.join import SqlJoin
|
||||||
|
|
||||||
@ -45,7 +44,7 @@ class Query:
|
|||||||
self.select_from: Union[Join, Table, List[str]] = []
|
self.select_from: Union[Join, Table, List[str]] = []
|
||||||
self.columns = [sqlalchemy.Column]
|
self.columns = [sqlalchemy.Column]
|
||||||
self.order_columns = order_bys
|
self.order_columns = order_bys
|
||||||
self.sorted_orders: OrderedDict[OrderAction, text] = OrderedDict()
|
self.sorted_orders: Dict[OrderAction, text] = {}
|
||||||
self._init_sorted_orders()
|
self._init_sorted_orders()
|
||||||
|
|
||||||
self.limit_raw_sql = limit_raw_sql
|
self.limit_raw_sql = limit_raw_sql
|
||||||
@ -183,7 +182,7 @@ class Query:
|
|||||||
pk_alias = self.model_cls.get_column_alias(self.model_cls.Meta.pkname)
|
pk_alias = self.model_cls.get_column_alias(self.model_cls.Meta.pkname)
|
||||||
pk_aliased_name = f"{self.table.name}.{pk_alias}"
|
pk_aliased_name = f"{self.table.name}.{pk_alias}"
|
||||||
qry_text = sqlalchemy.text(f"{pk_aliased_name}")
|
qry_text = sqlalchemy.text(f"{pk_aliased_name}")
|
||||||
maxes = OrderedDict()
|
maxes = {}
|
||||||
for order in list(self.sorted_orders.keys()):
|
for order in list(self.sorted_orders.keys()):
|
||||||
if order is not None and order.get_field_name_text() != pk_aliased_name:
|
if order is not None and order.get_field_name_text() != pk_aliased_name:
|
||||||
aliased_col = order.get_field_name_text()
|
aliased_col = order.get_field_name_text()
|
||||||
@ -37,8 +37,8 @@ from ormar.exceptions import (
|
|||||||
from ormar.queryset import FieldAccessor, FilterQuery, SelectAction
|
from ormar.queryset import FieldAccessor, FilterQuery, SelectAction
|
||||||
from ormar.queryset.actions.order_action import OrderAction
|
from ormar.queryset.actions.order_action import OrderAction
|
||||||
from ormar.queryset.clause import FilterGroup, QueryClause
|
from ormar.queryset.clause import FilterGroup, QueryClause
|
||||||
from ormar.queryset.prefetch_query import PrefetchQuery
|
from ormar.queryset.queries.prefetch_query import PrefetchQuery
|
||||||
from ormar.queryset.query import Query
|
from ormar.queryset.queries.query import Query
|
||||||
from ormar.queryset.reverse_alias_resolver import ReverseAliasResolver
|
from ormar.queryset.reverse_alias_resolver import ReverseAliasResolver
|
||||||
|
|
||||||
if TYPE_CHECKING: # pragma no cover
|
if TYPE_CHECKING: # pragma no cover
|
||||||
|
|||||||
@ -2,8 +2,7 @@ import databases
|
|||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
import ormar
|
import ormar
|
||||||
from ormar.models.mixins import ExcludableMixin
|
from ormar.queryset.queries.prefetch_query import sort_models
|
||||||
from ormar.queryset.prefetch_query import sort_models
|
|
||||||
from ormar.queryset.utils import (
|
from ormar.queryset.utils import (
|
||||||
subtract_dict,
|
subtract_dict,
|
||||||
translate_list_to_dict,
|
translate_list_to_dict,
|
||||||
|
|||||||
Reference in New Issue
Block a user