Skip to content

Commit c9fc5e5

Browse files
author
Stamatios Stamou Jr
committed
Added filters, authorization endpoints var and several minor adjustments
1 parent f273edc commit c9fc5e5

File tree

4 files changed

+693
-21
lines changed

4 files changed

+693
-21
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ class ResourceName(BaseResource):
9090
edit_fields = [
9191
'field1', 'field2', 'field3', 'field3'
9292
]
93+
94+
# define operator for searches
95+
search_operator = 'icontains'
9396
```
9497

9598
### Count
@@ -113,11 +116,21 @@ at your request. The api will return the total count of objects and will conside
113116

114117
To search you can use any field defined above in search_fields.
115118
The search will be applied in all fields defined using OR.
119+
By default all searches are made using icontains. You can change it for any allowed Django search operator.
116120

117121
```
118122
?search=value
119123
```
120124

125+
To change the search operator define it in you Resource Class
126+
127+
```
128+
class ResourceName(BaseResource):
129+
model = YOUR_DJANGO_MODEL
130+
131+
search_operator = 'icontains'
132+
```
133+
121134
### Filter
122135

123136
To filter just use querystrings. The filter will only be applied in defined fields above in filter_fields.

easyapi/base.py

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# from typing import Any
22

33
import decimal
4+
import importlib
45
import json
56
import re
67
from functools import reduce
@@ -17,16 +18,28 @@
1718

1819
from django.http import JsonResponse
1920

20-
21-
from modules.maintenance.util import find_connection
22-
from modules.orm.filters import Filter as OrmFilter
23-
from settings.context import session
2421
from .exception import HTTPException
2522

2623
re_id = re.compile(r'(.*)\/(\d+)(\/.)?$')
2724
search_regex = re.compile(r'__isnull|__gte|__lte|__lt|__gt|__startswith')
2825

2926

27+
async def fake_tenant(*args, **kwargs):
28+
return 'default'
29+
30+
31+
tenant = importlib.find_loader('tenant')
32+
if tenant:
33+
tenant = importlib.import_module('tenant')
34+
set_tenant = tenant.set_tenant
35+
OrmFilter = tenant.Filter
36+
session = tenant.session
37+
else:
38+
set_tenant = fake_tenant
39+
OrmFilter = None
40+
session = None
41+
42+
3043
async def method_not_allowed(self, **kwargs):
3144
raise HTTPException(405, 'Method not allowed')
3245

@@ -44,6 +57,7 @@ def decoder(obj):
4457

4558

4659
class BaseResource(View):
60+
authenticated = False
4761
allowed_methods = ['delete', 'get', 'patch', 'post']
4862
routes = []
4963

@@ -66,7 +80,6 @@ class BaseResource(View):
6680

6781
related_models = None
6882
list_related_fields = None
69-
# related_fields = []
7083
many_to_many_models = {}
7184

7285
filter_fields = []
@@ -88,7 +101,7 @@ class BaseResource(View):
88101
normalize_list = False
89102

90103
def __init__(self):
91-
user_session = session.get()
104+
user_session = session.get() if session else None
92105
self.account_id = user_session['account'].id if user_session else None
93106
self.account = user_session['account'] if user_session else None
94107
self.user = user_session['user'] if user_session else None
@@ -143,10 +156,11 @@ async def dispatch(self, request, *args, **kwargs) -> None:
143156
if func:
144157
self.allowed_methods = allowed_methods or self.allowed_methods
145158

159+
if self.authenticated and not self.user:
160+
raise HTTPException(401, 'Not authorized')
161+
146162
if method not in self.allowed_methods:
147-
return HTTPException(
148-
status=405, detail=f'{method} not allowed'
149-
)
163+
raise HTTPException(405, f'{method} not allowed')
150164

151165
if not func:
152166
handler = getattr(self, method, method_not_allowed)
@@ -313,7 +327,7 @@ def dehydrate(self, response):
313327

314328
# count só se aplica a listagens
315329
@sync_to_async
316-
def count(self):
330+
def count(self, account_db):
317331
count = 0
318332
self.count_results = 10
319333
if not hasattr(self.queryset, 'query'):
@@ -326,7 +340,6 @@ def count(self):
326340
f'SELECT count(DISTINCT {table}.id) FROM',
327341
query,
328342
)
329-
account_db = find_connection(self.account_id)
330343
connection = connections[account_db]
331344
cursor = connection.cursor()
332345
cursor.execute(query, params)
@@ -347,12 +360,13 @@ def get_filters(self, request):
347360
if not conditions:
348361
return
349362

350-
queryset = OrmFilter(
351-
self.model,
352-
self.user.timezone or 'UTC'
353-
)
354-
queryset = queryset.filter_by(conditions)
355-
self.queryset = queryset.distinct()
363+
if OrmFilter:
364+
queryset = OrmFilter(
365+
self.model,
366+
self.user.timezone if self.user else 'UTC'
367+
)
368+
queryset = queryset.filter_by(conditions)
369+
self.queryset = queryset.distinct()
356370

357371
async def return_results(self, results):
358372
if self.count_results:
@@ -392,7 +406,8 @@ async def get_objs(self, request):
392406
self.filter_objs()
393407

394408
if request.GET.get('count'):
395-
return await self.count()
409+
account_db = await set_tenant(self.account_id)
410+
return await self.count(account_db)
396411

397412
if self.page > 0:
398413
start = (self.page - 1) * self.limit
@@ -600,14 +615,14 @@ async def patch(self, request):
600615
body = request.json
601616
except Exception:
602617
return HTTPException(
603-
status=400, detail='Invalid body'
618+
400, 'Invalid body'
604619
)
605620
match = re_id.match(request.path_info)
606621
if match:
607622
results = await self._update_obj(match[2], body)
608623
return self.serialize(results)
609624
else:
610-
return HTTPException(status=404, detail="Item not found")
625+
return HTTPException(404, "Item not found")
611626

612627
#########################################################
613628
# POST

0 commit comments

Comments
 (0)