Skip to content

Commit f167edd

Browse files
authored
feature: added utils to allow apply filters and orderins without using dataclasses (#27)
1 parent fd0263a commit f167edd

File tree

4 files changed

+130
-1
lines changed

4 files changed

+130
-1
lines changed

dataclass_sqlalchemy_mixins/base/utils.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,61 @@ def get_unary_expressions(
2424
return SqlAlchemyOrderConverterMixin().get_unary_expressions(
2525
order_by=order_by, model=model
2626
)
27+
28+
29+
def apply_filters(
30+
query,
31+
filters: tp.Dict[str, tp.Any],
32+
model: tp.Type[DeclarativeMeta] = None,
33+
):
34+
converter = SqlAlchemyFilterConverterMixin()
35+
36+
filters_binary_expressions = converter.get_models_binary_expressions(
37+
model=model,
38+
filters=filters,
39+
)
40+
41+
models_to_join = []
42+
binary_expressions = []
43+
44+
for binary_expression in filters_binary_expressions:
45+
models_to_join += binary_expression["models"]
46+
binary_expressions.append(binary_expression["binary_expression"])
47+
48+
# Checking if there are other models required to be joined
49+
if models_to_join != [
50+
model,
51+
]:
52+
query = converter.join_models(query=query, models=models_to_join)
53+
54+
query = query.filter(*binary_expressions)
55+
return query
56+
57+
58+
def apply_order_by(
59+
query,
60+
order_by: tp.Union[str, tp.List[str]],
61+
model: tp.Type[DeclarativeMeta] = None,
62+
):
63+
converter = SqlAlchemyOrderConverterMixin()
64+
65+
order_by_unary_expressions = converter.get_models_unary_expressions(
66+
model=model,
67+
order_by=order_by,
68+
)
69+
70+
models_to_join = []
71+
unary_expressions = []
72+
73+
for binary_expression in order_by_unary_expressions:
74+
models_to_join += binary_expression["models"]
75+
unary_expressions.append(binary_expression["unary_expression"])
76+
77+
# Checking if there are other models required to be joined
78+
if models_to_join != [
79+
model,
80+
]:
81+
query = converter.join_models(query=query, models=models_to_join)
82+
83+
query = query.order_by(*unary_expressions)
84+
return query

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "dataclass-sqlalchemy-mixins"
3-
version = "0.2.0"
3+
version = "0.3.0"
44
description = "Allows to convert dataclasses to sqlalchemy filters and orderings."
55
authors = ["ViAchKoN"]
66
readme = "README.md"

tests/filtering/test_fields_filters.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,39 @@ def test_filter__utils__eq__ok(
8787
assert result.as_dict() == expected_item.as_dict()
8888

8989

90+
def test_filter__utils__apply__eq__ok(
91+
db_session,
92+
get_sqlalchemy_filter_base_model,
93+
):
94+
expected_item_name = "expected_item_name"
95+
96+
# Create expected item
97+
expected_item = models_factory.ItemFactory.create(name=expected_item_name)
98+
99+
# Create unexpected items
100+
models_factory.ItemFactory.create_batch(size=4)
101+
102+
assert db_session.query(models.Item).count() == 5
103+
104+
query = db_session.query(models.Item)
105+
106+
query = utils.apply_filters(
107+
query=query,
108+
filters={
109+
"name": expected_item_name,
110+
},
111+
model=models.Item,
112+
)
113+
114+
results = query.all()
115+
116+
assert len(results) == 1
117+
118+
result = results[0]
119+
120+
assert result.as_dict() == expected_item.as_dict()
121+
122+
90123
@pytest.mark.parametrize(
91124
"apply_filters",
92125
[

tests/ordering/test_fields_orderings.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,44 @@ def test_order_by_id__utils__ok(
9494
assert result.as_dict() == expected_item.as_dict()
9595

9696

97+
def test_order_by_id__utils__apply__ok(
98+
db_session,
99+
):
100+
items = models_factory.ItemFactory.create_batch(size=5)
101+
102+
for order_by in [
103+
"id",
104+
[
105+
"id",
106+
],
107+
"-id",
108+
[
109+
"-id",
110+
],
111+
]:
112+
expected_items = items
113+
if order_by in [
114+
"-id",
115+
[
116+
"-id",
117+
],
118+
]:
119+
expected_items = list(reversed(items))
120+
121+
query = db_session.query(models.Item)
122+
123+
query = utils.apply_order_by(
124+
query=query,
125+
order_by=order_by,
126+
model=models.Item,
127+
)
128+
129+
results = query.all()
130+
131+
for expected_item, result in zip(expected_items, results):
132+
assert result.as_dict() == expected_item.as_dict()
133+
134+
97135
@pytest.mark.parametrize(
98136
"apply_order_by",
99137
[

0 commit comments

Comments
 (0)