Skip to content

Commit

Permalink
Merge pull request #8 from iashraful/feature/issue#5-filtering
Browse files Browse the repository at this point in the history
Issue #5 Enable filtering options
  • Loading branch information
iashraful committed Aug 12, 2020
2 parents 8e83449 + 85ff6b8 commit d9b260a
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 8 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 2.0.0
**ADDED**
* Dynamic API filtering with model fields.
* Support all the django filter on API params. Like: ?search=1&title:icontains=test

**UPDATED**
* Settings config data type updated with default configuration

## 1.0.10
**ADDED**
* Added Dockerfile and compose file for local dependency
Expand Down
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ It's easy and configurable.

### Quick Start
* Install the library inside your virtualenv by using pip `pip install fast-drf`
* Add your apps to `FAST_API_ENABLED_APPS` on settings for best performance. Like, `FAST_API_ENABLED_APPS=['app_name', 'my_app']`
* Add config for Fast DRF like following,
```python
FAST_DRF_CONFIG = {
'DEFAULT_APPLIED_APPS': (
'example_app', 'another_app'
)
}
```
* Update your every model or if you use base abstract model then it's good and less time you need. Update model like following,
```python
from fast_drf.mixins.expose_api_model_mixin import ExposeApiModelMixin
Expand Down Expand Up @@ -72,7 +79,13 @@ Set `APPEND_SLASH = True` at your settings.py

#### API Prefix Change
Set you API prefix as your own like following.
`API_PREFIX = 'rest-api'` Default **api**
```python
FAST_DRF_CONFIG = {
# ...
'DEFAULT_API_PREFIX': 'rest-api' # Default 'api'
# ...
}
```
Your API will look like, `/rest-api/v1/users/`


Expand Down
20 changes: 15 additions & 5 deletions fast_drf/core/viewset_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

__author__ = 'Ashraful'

from fast_drf.mixins.api_filtered_mixin import APIFilteredMixin


class APIViewSetGenerator(object):
permission_classes = None
Expand Down Expand Up @@ -43,10 +45,21 @@ class RunTimeViewset(viewsets.ModelViewSet):
model = self.model
lookup_field = self.lookup_field

def list(self, request, **kwargs):
def get_queryset(self, *args, **kwargs):
# Here it's performing sub query in SQL. So, no performance loss. Just executing a big query
# not more than 1 query
self.queryset = self.model.objects.filter(pk__in=self.queryset)
return self.model.objects.filter(pk__in=self.queryset)

def list(self, request, **kwargs):
base_queryset = self.get_queryset(request=request, **kwargs)
request = kwargs.get('request', self.request)
try:
search_enabled = bool(eval(request.GET.get('search', '0')))
if search_enabled:
_filters = APIFilteredMixin.get_filters(model=self.model, request=request)
self.queryset = base_queryset.filter(_filters)
except Exception as err:
self.queryset = base_queryset
return super(RunTimeViewset, self).list(request=request, **kwargs)

def create(self, request, *args, **kwargs):
Expand All @@ -68,7 +81,4 @@ def partial_update(self, request, pk=None, *args, **kwargs):
def destroy(self, request, pk=None, *args, **kwargs):
return super(RunTimeViewset, self).destroy(request=request, pk=pk, *args, **kwargs)

def get_queryset(self, *args, **kwargs):
return self.model.objects.filter(pk__in=self.queryset)

return RunTimeViewset
37 changes: 37 additions & 0 deletions fast_drf/mixins/api_filtered_mixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from copy import deepcopy

from django.db.models import Q


class APIFilteredMixin:
"""
DO NOT INCLUDE THIS CLASS TO ANY MODEL, VIEW OR ANYWHERE
Basically it'll parse the request params and return django queryset format
"""


@classmethod
def get_filters(cls, model, request, **kwargs):
"""
model:
"""
_fields = [f.name for f in model._meta.get_fields()]
_params = request.GET
_filters = {}
for param, val in _params.items():
try:
if ':' in param:
_field_name, _filter_option = param.split(':')
if _field_name not in _fields:
continue
_temp = deepcopy(param)
_filters['{}__{}'.format(_field_name, _filter_option)] = val
else:
if param not in _fields:
continue
_filters[param] = val
except Exception as error:
continue
return Q(**_filters)

2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

setup(
name='fast-drf',
version='1.0.10',
version='2.0.0',
packages=find_packages(),
include_package_data=True,
license='MIT License',
Expand Down

0 comments on commit d9b260a

Please sign in to comment.