Skip to content

Commit f34a12d

Browse files
authored
Merge pull request #177 from TMiguelT/filter-related
Automatically filter by the parent resource
2 parents 4c102b8 + bd7da79 commit f34a12d

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

flask_rest_jsonapi/data_layers/alchemy.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,21 @@ def get_object(self, view_kwargs, qs=None):
9999

100100
return obj
101101

102-
def get_collection(self, qs, view_kwargs):
102+
def get_collection(self, qs, view_kwargs, filters=None):
103103
"""Retrieve a collection of objects through sqlalchemy
104104
105105
:param QueryStringManager qs: a querystring manager to retrieve information from url
106106
:param dict view_kwargs: kwargs from the resource view
107+
:param dict filters: A dictionary of key/value filters to apply to the eventual query
107108
:return tuple: the number of object and the list of objects
108109
"""
109110
self.before_get_collection(qs, view_kwargs)
110111

111112
query = self.query(view_kwargs)
112113

114+
if filters:
115+
query = query.filter_by(**filters)
116+
113117
if qs.filters:
114118
query = self.filter_query(query, qs.filters, self.model)
115119

flask_rest_jsonapi/data_layers/base.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,12 @@ def get_object(self, view_kwargs):
6060
"""
6161
raise NotImplementedError
6262

63-
def get_collection(self, qs, view_kwargs):
63+
def get_collection(self, qs, view_kwargs, filters=None):
6464
"""Retrieve a collection of objects
6565
6666
:param QueryStringManager qs: a querystring manager to retrieve information from url
6767
:param dict view_kwargs: kwargs from the resource view
68+
:param dict filters: A dictionary of key/value filters to apply to the eventual query
6869
:return tuple: the number of object and the list of objects
6970
"""
7071
raise NotImplementedError

flask_rest_jsonapi/resource.py

+22-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from flask_rest_jsonapi.data_layers.base import BaseDataLayer
2222
from flask_rest_jsonapi.data_layers.alchemy import SqlalchemyDataLayer
2323
from flask_rest_jsonapi.utils import JSONEncoder
24+
from marshmallow_jsonapi.fields import BaseRelationship
2425

2526

2627
class ResourceMeta(MethodViewType):
@@ -116,7 +117,8 @@ def get(self, *args, **kwargs):
116117

117118
qs = QSManager(request.args, self.schema)
118119

119-
objects_count, objects = self.get_collection(qs, kwargs)
120+
parent_filter = self._get_parent_filter(request.url, kwargs)
121+
objects_count, objects = self.get_collection(qs, kwargs, filters=parent_filter)
120122

121123
schema_kwargs = getattr(self, 'get_schema_kwargs', dict())
122124
schema_kwargs.update({'many': True})
@@ -186,6 +188,23 @@ def post(self, *args, **kwargs):
186188

187189
return result
188190

191+
def _get_parent_filter(self, url, kwargs):
192+
"""
193+
Returns a dictionary of filters that should be applied to ensure only resources
194+
belonging to the parent resource are returned
195+
"""
196+
197+
url_segments = url.split('/')
198+
parent_segment = url_segments[-3]
199+
parent_id = url_segments[-2]
200+
201+
for key, value in self.schema._declared_fields.items():
202+
if isinstance(value, BaseRelationship):
203+
if value.type_ == parent_segment:
204+
return {value.id_field: parent_id}
205+
206+
return {}
207+
189208
def before_get(self, args, kwargs):
190209
"""Hook to make custom work before get method"""
191210
pass
@@ -205,8 +224,8 @@ def after_post(self, result):
205224
def before_marshmallow(self, args, kwargs):
206225
pass
207226

208-
def get_collection(self, qs, kwargs):
209-
return self._data_layer.get_collection(qs, kwargs)
227+
def get_collection(self, qs, kwargs, filters=None):
228+
return self._data_layer.get_collection(qs, kwargs, filters=filters)
210229

211230
def create_object(self, data, kwargs):
212231
return self._data_layer.create_object(data, kwargs)

0 commit comments

Comments
 (0)