Skip to content

Commit

Permalink
fix(smart_fields): don't compute smart field on null relations (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbarreau authored Oct 20, 2023
1 parent f025903 commit c588940
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 4 deletions.
4 changes: 2 additions & 2 deletions django_forest/resources/utils/smart_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@ def _handle_smart_field_on_relations(self, queryset, base_collection, params, ma
def _handle_smart_field_for_relation(self, queryset, relation_field, collection_name, params, many):
if many:
for item in queryset:
if hasattr(item, relation_field["field"]):
if getattr(item, relation_field["field"], None) is not None:
self.handle_smart_fields(
getattr(item, relation_field["field"]), collection_name, params, False, False
)
else:
if hasattr(queryset, relation_field["field"]):
if getattr(queryset, relation_field["field"], None) is not None:
self.handle_smart_fields(
getattr(queryset, relation_field["field"]), collection_name, params, False, False
)
Expand Down
3 changes: 2 additions & 1 deletion django_forest/tests/forest/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django_forest.tests.forest.choice import ChoiceForest
from django_forest.tests.forest.question import QuestionForest
from django_forest.tests.forest.place import PlaceForest

__all__ = ['QuestionForest', 'ChoiceForest']
__all__ = ['QuestionForest', 'ChoiceForest', 'PlaceForest']
25 changes: 25 additions & 0 deletions django_forest/tests/forest/place.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from django_forest.tests.models import Place
from django_forest.utils.collection import Collection

from django_forest.resources.utils.resource import ResourceView
from django_forest.resources.views import ListView, DetailView

class PlaceForest(Collection):
def load(self):
self.fields = [
{
'field': 'restaurant',
"reference": "tests_restaurant.id",
'type': 'String',
"filter": self.filter_restaurant,
"is_filterable": True,

}
]

def filter_restaurant(self, obj):
if obj.restaurant:
return obj.restaurant
return None

Collection.register(PlaceForest, Place)
57 changes: 57 additions & 0 deletions django_forest/tests/resources/views/list/test_list_smart_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ def setUp(self):
Schema.add_smart_features()
Schema.handle_json_api_schema()
self.url = reverse('django_forest:resources:list', kwargs={'resource': 'tests_question'})
self.place_url = reverse('django_forest:resources:list', kwargs={'resource': 'tests_place'})

self.client = self.client_class(
HTTP_AUTHORIZATION='Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjUiLCJlbWFpbCI6Imd1aWxsYXVtZWNAZm9yZXN0YWRtaW4uY29tIiwiZmlyc3RfbmFtZSI6Ikd1aWxsYXVtZSIsImxhc3RfbmFtZSI6IkNpc2NvIiwidGVhbSI6Ik9wZXJhdGlvbnMiLCJyZW5kZXJpbmdfaWQiOjEsImV4cCI6MTYyNTY3OTYyNi44ODYwMTh9.mHjA05yvMr99gFMuFv0SnPDCeOd2ZyMSN868V7lsjnw')
ScopeManager.cache = {
Expand All @@ -61,6 +63,61 @@ def tearDown(self):
ScopeManager.cache = {}
Collection._registry = {}

@mock.patch('jose.jwt.decode', return_value={'id': 1, 'rendering_id': 1})
@freeze_time(
lambda: datetime(2021, 7, 8, 9, 20, 23, 582772, tzinfo=get_timezone('UTC'))
)
def test_search_on_belongs_to(self, mocked_decode):
response = self.client.get(self.place_url, {
"context[relationship]": "BelongsTo",
"context[field]": "restaurant",
"context[collection]": "polls_place",
"context[recordId]": "1",
"fields[tests_restaurant]": "id",
"fields[restaurant]": "id",
"page[number]": "1",
"page[size]": "100",
"search": "1",
"searchExtended": "0",
"searchToEdit": "true"
})
data = response.json()
self.assertEqual(response.status_code, 200)
self.assertEqual(data, {
'data': [
{
"type": 'tests_place',
"id": 1,
"attributes": {'name': 'San Marco', 'address': 'Venezia, Italia'},
"relationships": {
"restaurant": {
"links": {'related': '/forest/tests_place/1/relationships/restaurant'},
"data": {'type': 'tests_restaurant', 'id': '1'},
}
},
"links": {'self': '/forest/tests_place/1'},
}
],
"included":[
{
'type': 'tests_restaurant',
'relationships': {
'place': {
'links': {'related': '/forest/tests_restaurant/1/relationships/place'}
},
'waiter_set': {
'links': {'related': '/forest/tests_restaurant/1/relationships/waiter_set'}
}
},
'attributes': {'serves_pizza': True, 'serves_hot_dogs': True},
'links': {'self': '/forest/tests_restaurant/1'},
'id': 1
}
],
"meta":{'decorators': [{'id': 1, 'search': ['id']}]},
}
)

@mock.patch('jose.jwt.decode', return_value={'id': 1, 'rendering_id': 1})
@freeze_time(
lambda: datetime(2021, 7, 8, 9, 20, 23, 582772, tzinfo=get_timezone('UTC'))
Expand Down
2 changes: 1 addition & 1 deletion django_forest/tests/utils/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def test_add_smart_features(self, collection_mock):
Schema.add_smart_features()
from django_forest.tests.forest import QuestionForest
from django_forest.tests.models import Question
collection_mock.register.assert_called_with(QuestionForest, Question)
collection_mock.register.assert_any_call(QuestionForest, Question)

def test_get_collection(self):
collection = Schema.get_collection('tests_question')
Expand Down

0 comments on commit c588940

Please sign in to comment.