Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e0d6916

Browse files
2.0.0 Release 🚀😄 adding new filters and capabilities to create your own filters
2 parents d64b2a8 + bfedebf commit e0d6916

File tree

12 files changed

+269
-48
lines changed

12 files changed

+269
-48
lines changed

‎.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
11
__pycache__
2+
build/
3+
dist/
4+
*.egg-info
5+
*.swp
6+
*.pyc

‎README.md

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pip install nocodb
1414
### Client configuration
1515
```python
1616
from nocodb.nocodb import NocoDBProject, APIToken, JWTAuthToken
17-
from nocodb.filters import InFilter, EqFilter
17+
from nocodb.filters import LikeFilter, EqFilter
1818
from nocodb.infra.requests_client import NocoDBRequestsClient
1919

2020

@@ -98,7 +98,7 @@ table_rows = client.table_row_list(project, table_name, params={'offset': 100})
9898
# Filter the query
9999
# Currently only one filter at a time is allowed. I don't know how to join
100100
# multiple conditions in nocodb dsl. If you know how please let me know :).
101-
table_rows = client.table_row_list(project, table_name, InFilter("name", "sam"))
101+
table_rows = client.table_row_list(project, table_name, LikeFilter("name", "%sam%"))
102102
table_rows = client.table_row_list(project, table_name, filter_obj=EqFilter("Id", 100))
103103

104104
# Filter and count rows
@@ -114,22 +114,101 @@ row = client.table_row_detail(project, table_name, row_id)
114114
# Create a new row
115115
row_info = {
116116
"name": "my thoughts",
117-
"content": "i'm going to buy samuel a beer because i love this module",
117+
"content": "i'm going to buy samuel a beer 🍻 because I 💚 this module",
118118
"mood": ":)"
119119
}
120120
client.table_row_create(project, table_name, row_info)
121121

122122
# Update a row
123123
row_id = 2
124124
row_info = {
125-
"content": "i'm going to buy samuel a new car because i love this module",
125+
"content": "i'm going to buy samuel a new car 🚙 because I 💚 this module",
126126
}
127127
client.table_row_update(project, table_name, row_id, row_info)
128128

129129
# Delete a row (only if you've already bought me a beer)
130130
client.table_row_delete(project, table_name, row_id)
131131
```
132132

133+
### Available filters
134+
135+
- EqFilter
136+
- EqualFilter (Alias of EqFilter)
137+
- NotEqualFilter
138+
- GreaterThanFilter
139+
- GreaterOrEqualFilter
140+
- LessThanFilter
141+
- LessOrEqualFilter
142+
- LikeFilter
143+
144+
### Using custom filters
145+
146+
Nocodb is evolving and new operators are coming with each release.
147+
148+
Most of the basic operations are inside this package but you could need some new
149+
feature that could not be added yet.
150+
For those filters you can build your own.
151+
152+
Example for basic filters:
153+
154+
```python
155+
from nocodb.filters.factory import basic_filter_class_factory
156+
157+
BasicFilter = basic_filter_class_factory('=')
158+
table_rows = client.table_row_list(project, table_name, BasicFilter('age', '16'))
159+
160+
```
161+
162+
You can find the updated list of all the available nocodb operators [here](https://docs.nocodb.com/developer-resources/rest-apis/#comparison-operators).
163+
164+
In some cases you might want to write your own filter string as described in the previous link.
165+
For that cases you can use the less-semmantic RawFilter.
166+
167+
```python
168+
from nocodb.filters.raw_filter import RawFilter
169+
170+
table_rows = client.table_row_list(project, table_name, RawFilter('(birthday,eq,exactDate,2023年06月01日)'))
171+
```
172+
173+
In some cases we might want to have a file with some custom raw filters already defined by us.
174+
We can easily create custom raw filter classes using `raw_template_filter_class_factory`.
175+
176+
```python
177+
from nocodb.filters.factory import raw_template_filter_class_factory
178+
179+
BirthdayDateFilter = raw_template_filter_class_factory('(birthday,eq,exactDate,{})')
180+
ExactDateEqFilter = raw_template_filter_class_factory('({},eq,exactDate,{})')
181+
ExactDateOpFilter = raw_template_filter_class_factory('({},{op},exactDate,{})')
182+
183+
table_rows = client.table_row_list(project, table_name, BirthdayDateFilter('2023年06月01日'))
184+
table_rows = client.table_row_list(project, table_name, ExactDateEqFilter('column', '2023年06月01日'))
185+
table_rows = client.table_row_list(project, table_name, ExactDateOpFilter('column', '2023年06月01日', op='eq'))
186+
```
187+
188+
```python
189+
from nocodb import filters
190+
191+
# Basic filters...
192+
nick_filter = filters.EqFilter("nickname", "elchicodepython")
193+
country_filter = filters.EqFilter("country", "es")
194+
girlfriend_code = filters.EqFilter("gfcode", "404")
195+
current_mood_code = filters.EqFilter("moodcode", "418")
196+
197+
# Combining filters using logical filters
198+
or_filter = filters.Or(nick_filter, country_filter)
199+
and_filter = filters.And(girlfriend_code, current_mood_code)
200+
201+
# Negating filters with a Not filter
202+
not_me = filters.Not(filters.EqFilter("nickname", "elchicodepython"))
203+
204+
# You can also combine combinations
205+
or_combined_filter = filters.Or(or_filter, and_filter)
206+
and_combined_filter = filters.And(or_filter, and_filter)
207+
208+
```
209+
210+
Credits to @MitPitt for asking this feature.
211+
133212
## Author notes
134213

135214
I created this package to bootstrap some personal projects and I hope it

‎nocodb/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.0.1"
1+
__version__ = "2.0.0"

‎nocodb/filters.py

Lines changed: 0 additions & 19 deletions
This file was deleted.

‎nocodb/filters/__init__.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from .factory import basic_filter_class_factory
2+
from .logical import And, Not, Or
3+
4+
EqFilter = basic_filter_class_factory("eq")
5+
EqualFilter = EqFilter
6+
NotEqualFilter = basic_filter_class_factory("neq")
7+
GreaterThanFilter = basic_filter_class_factory("gt")
8+
GreaterOrEqualFilter = basic_filter_class_factory("ge")
9+
LessThanFilter = basic_filter_class_factory("lt")
10+
LessOrEqualFilter = basic_filter_class_factory("le")
11+
LikeFilter = basic_filter_class_factory("like")
12+
13+
__all__ = [
14+
"And",
15+
"Not",
16+
"Or",
17+
"EqFilter",
18+
"EqualFilter",
19+
"NotEqualFilter",
20+
"GreaterThanFilter",
21+
"GreaterOrEqualFilter",
22+
"LessThanFilter",
23+
"LessOrEqualFilter",
24+
"LikeFilter",
25+
]

‎nocodb/filters/factory.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from ..nocodb import WhereFilter
2+
3+
from .raw_filter import RawTemplateFilter
4+
5+
6+
def basic_filter_class_factory(filter_name: str):
7+
return raw_template_filter_class_factory('({},' + filter_name + ',{})')
8+
9+
def raw_template_filter_class_factory(template: str):
10+
class WrappedFilter(WhereFilter):
11+
def __init__(self, *args, **kwargs):
12+
self.__filter = RawTemplateFilter(template, *args, **kwargs)
13+
def get_where(self) -> str:
14+
return self.__filter.get_where()
15+
return WrappedFilter

‎nocodb/filters/factory_test.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from .factory import basic_filter_class_factory, raw_template_filter_class_factory
2+
3+
4+
def test_basic_filter_class_factory():
5+
FilterClass = basic_filter_class_factory('eq')
6+
assert FilterClass('column', 'value').get_where() == '(column,eq,value)'
7+
8+
9+
def test_raw_template_filter_class_factory():
10+
FilterClassWithoutParams = raw_template_filter_class_factory('()')
11+
FilterClassWithParams = raw_template_filter_class_factory('({},{},{})')
12+
FilterClassWithKwargs = raw_template_filter_class_factory('({},{op},{})')
13+
assert FilterClassWithoutParams().get_where() == '()'
14+
assert FilterClassWithParams('1', '2','3').get_where() == '(1,2,3)'
15+
assert FilterClassWithKwargs('1', '2', op='eq').get_where() == '(1,eq,2)'

‎nocodb/filters/filters_test.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import pytest
2+
3+
from .. import filters
4+
5+
from ..nocodb import WhereFilter
6+
7+
8+
@pytest.mark.parametrize(
9+
"filter_class, expected_operator",
10+
[
11+
(filters.EqFilter, "eq"),
12+
(filters.EqualFilter, "eq"),
13+
(filters.NotEqualFilter, "neq"),
14+
(filters.GreaterOrEqualFilter, "ge"),
15+
(filters.GreaterThanFilter, "gt"),
16+
(filters.LessThanFilter, "lt"),
17+
(filters.LessOrEqualFilter, "le"),
18+
(filters.LikeFilter, "like"),
19+
],
20+
)
21+
def test_basic_filters_are_correctly_created(
22+
filter_class: WhereFilter, expected_operator: str
23+
):
24+
test_filter = filter_class("column", "value")
25+
assert test_filter.get_where() == f"(column,{expected_operator},value)"
26+
27+
28+
def test_or_filter():
29+
nick_filter = filters.EqFilter("nickname", "elchicodepython")
30+
country_filter = filters.EqFilter("country", "es")
31+
nick_or_country_filter = filters.Or(nick_filter, country_filter)
32+
assert (
33+
nick_or_country_filter.get_where()
34+
== "((nickname,eq,elchicodepython)~or(country,eq,es))"
35+
)
36+
37+
38+
def test_and_filter():
39+
nick_filter = filters.EqFilter("nickname", "elchicodepython")
40+
country_filter = filters.EqFilter("country", "es")
41+
nick_or_country_filter = filters.And(nick_filter, country_filter)
42+
assert (
43+
nick_or_country_filter.get_where()
44+
== "((nickname,eq,elchicodepython)~and(country,eq,es))"
45+
)
46+
47+
48+
def test_combined_filter():
49+
nick_filter = filters.EqFilter("nickname", "elchicodepython")
50+
country_filter = filters.EqFilter("country", "es")
51+
girlfriend_code = filters.EqFilter("gfcode", "404")
52+
current_mood_code = filters.EqFilter("moodcode", "418")
53+
or_filter = filters.Or(nick_filter, country_filter)
54+
and_filter = filters.And(girlfriend_code, current_mood_code)
55+
or_combined_filter = filters.Or(or_filter, and_filter)
56+
and_combined_filter = filters.And(or_filter, and_filter)
57+
58+
assert (
59+
or_combined_filter.get_where()
60+
== "(((nickname,eq,elchicodepython)~or(country,eq,es))~or((gfcode,eq,404)~and(moodcode,eq,418)))"
61+
)
62+
assert (
63+
and_combined_filter.get_where()
64+
== "(((nickname,eq,elchicodepython)~or(country,eq,es))~and((gfcode,eq,404)~and(moodcode,eq,418)))"
65+
)
66+
67+
68+
def test_not_filter():
69+
me = filters.EqFilter("nickname", "elchicodepython")
70+
not_me = filters.Not(me)
71+
assert not_me.get_where() == "~not(nickname,eq,elchicodepython)"

‎nocodb/filters/logical.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from typing import List
2+
from ..nocodb import WhereFilter
3+
4+
5+
class Or(WhereFilter):
6+
def __init__(self, *filters: List[WhereFilter]):
7+
self.__filters = filters
8+
9+
def get_where(self) -> str:
10+
return (
11+
"("
12+
+ "~or".join([filter.get_where() for filter in self.__filters])
13+
+ ")"
14+
)
15+
16+
17+
class And(WhereFilter):
18+
def __init__(self, *filters: List[WhereFilter]):
19+
self.__filters = filters
20+
21+
def get_where(self) -> str:
22+
return (
23+
"("
24+
+ "~and".join([filter.get_where() for filter in self.__filters])
25+
+ ")"
26+
)
27+
28+
29+
class Not(WhereFilter):
30+
def __init__(self, filter: WhereFilter):
31+
self.__filter = filter
32+
33+
def get_where(self) -> str:
34+
return "~not" + self.__filter.get_where()

‎nocodb/filters/raw_filter.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from ..nocodb import WhereFilter
2+
3+
4+
class RawFilter(WhereFilter):
5+
def __init__(self, raw: str):
6+
self.__raw = raw
7+
8+
def get_where(self) -> str:
9+
return self.__raw
10+
11+
12+
class RawTemplateFilter(WhereFilter):
13+
def __init__(self, template: str, *args, **kwargs):
14+
self.__template = template
15+
self.__template_values = args
16+
self.__template_kvalues = kwargs
17+
18+
def get_where(self) -> str:
19+
return self.__template.format(*self.__template_values, **self.__template_kvalues)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /