Skip to content

Commit 24504cf

Browse files
(temporary) fix for django-elasticsearch-dsl nested fields issue
1 parent 3f28002 commit 24504cf

File tree

5 files changed

+257
-37
lines changed

5 files changed

+257
-37
lines changed

examples/simple/books/models/address.py

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import unicode_literals
22

33
from django.db import models
4+
from django_elasticsearch_dsl_drf.wrappers import dict_to_obj
45

56
from six import python_2_unicode_compatible
67

@@ -52,17 +53,31 @@ def location_field_indexing(self):
5253
'lon': self.longitude,
5354
}
5455

55-
# @property
56-
# def country_indexing(self):
57-
# """Country data (nested) for indexing.
58-
#
59-
# :return:
60-
# """
61-
# return {
62-
# 'country': {
63-
# 'name': self.city.country.name,
64-
# 'city': {
65-
# 'name': self.city.name
66-
# }
67-
# }
68-
# }
56+
@property
57+
def country_indexing(self):
58+
"""Country data (nested) for indexing.
59+
60+
Example:
61+
62+
>>> mapping = {
63+
>>> 'country': {
64+
>>> 'name': 'Netherlands',
65+
>>> 'province': {
66+
>>> 'name': 'North Holland',
67+
>>> 'city': {
68+
>>> 'name': 'Amsterdam',
69+
>>> }
70+
>>> }
71+
>>> }
72+
>>> }
73+
74+
:return:
75+
"""
76+
wrapper = dict_to_obj({
77+
'name': self.city.country.name,
78+
'city': {
79+
'name': self.city.name
80+
}
81+
})
82+
83+
return wrapper

examples/simple/search_indexes/documents/address.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -89,29 +89,29 @@ class AddressDocument(DocType):
8989
}
9090
)
9191

92-
# # Country object
93-
# country = fields.NestedField(
94-
# attr='country_indexing',
95-
# properties={
96-
# 'name': StringField(
97-
# analyzer=html_strip,
98-
# fields={
99-
# 'raw': KeywordField(),
100-
# 'suggest': fields.CompletionField(),
101-
# }
102-
# ),
103-
# 'city': fields.ObjectField(
104-
# properties={
105-
# 'name': StringField(
106-
# analyzer=html_strip,
107-
# fields={
108-
# 'raw': KeywordField(),
109-
# }
110-
# )
111-
# }
112-
# )
113-
# }
114-
# )
92+
# Country object
93+
country = fields.NestedField(
94+
attr='country_indexing',
95+
properties={
96+
'name': StringField(
97+
analyzer=html_strip,
98+
fields={
99+
'raw': KeywordField(),
100+
'suggest': fields.CompletionField(),
101+
}
102+
),
103+
'city': fields.NestedField(
104+
properties={
105+
'name': StringField(
106+
analyzer=html_strip,
107+
fields={
108+
'raw': KeywordField(),
109+
}
110+
)
111+
}
112+
)
113+
}
114+
)
115115

116116
location = fields.GeoPointField(attr='location_field_indexing')
117117

src/django_elasticsearch_dsl_drf/tests/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from .test_search import TestSearch
1212
from .test_serializers import TestSerializers
1313
from .test_views import TestViews
14+
from .test_wrappers import TestWrappers
1415

1516
__title__ = 'django_elasticsearch_dsl_drf.tests'
1617
__author__ = 'Artur Barseghyan <[email protected]>'
@@ -27,4 +28,5 @@
2728
'TestSearch',
2829
'TestSerializers',
2930
'TestViews',
31+
'TestWrappers',
3032
)
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Test wrappers.
4+
"""
5+
6+
from __future__ import absolute_import, unicode_literals
7+
8+
import unittest
9+
10+
import pytest
11+
12+
from ..wrappers import obj_to_dict, dict_to_obj
13+
14+
__title__ = 'django_elasticsearch_dsl_drf.tests.test_wrappers'
15+
__author__ = 'Artur Barseghyan <[email protected]>'
16+
__copyright__ = '2017-2018 Artur Barseghyan'
17+
__license__ = 'GPL 2.0/LGPL 2.1'
18+
__all__ = (
19+
'TestWrappers',
20+
)
21+
22+
23+
@pytest.mark.django_db
24+
class TestWrappers(unittest.TestCase):
25+
"""Test helpers."""
26+
27+
@classmethod
28+
def setUpClass(cls):
29+
cls.mapping = {
30+
'country': {
31+
'name': 'Netherlands',
32+
'province': {
33+
'name': 'North Holland',
34+
'city': {
35+
'name': 'Amsterdam',
36+
}
37+
}
38+
}
39+
}
40+
41+
def test_obj_to_dict(self):
42+
"""Test `obj_to_dict`.
43+
44+
:return:
45+
"""
46+
wrapper = dict_to_obj(self.mapping)
47+
self.assertEqual(
48+
wrapper.country.name,
49+
self.mapping['country']['name']
50+
)
51+
52+
self.assertEqual(
53+
wrapper.country.province.name,
54+
self.mapping['country']['province']['name']
55+
)
56+
57+
self.assertEqual(
58+
wrapper.country.province.city.name,
59+
self.mapping['country']['province']['city']['name']
60+
)
61+
62+
# See if original ``mapping`` is same as ``as_dict``
63+
self.assertEqual(
64+
wrapper.as_dict,
65+
self.mapping
66+
)
67+
68+
# Since we don't know for sure which one will be, we need to make
69+
# sure it's one of the items.
70+
self.assertIn(
71+
str(wrapper),
72+
(
73+
self.mapping['country']['name'],
74+
self.mapping['country']['province']['name'],
75+
self.mapping['country']['province']['city']['name'],
76+
)
77+
)
78+
79+
def test_dict_to_obj(self):
80+
"""Test `dict_to_obj`.
81+
82+
:return:
83+
"""
84+
wrapper = dict_to_obj(self.mapping)
85+
mapping = obj_to_dict(wrapper)
86+
self.assertEqual(self.mapping, mapping)
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import json
2+
from six import python_2_unicode_compatible
3+
4+
__title__ = 'django_elasticsearch_dsl_drf.wrappers'
5+
__author__ = 'Artur Barseghyan <[email protected]>'
6+
__copyright__ = '2017-2018 Artur Barseghyan'
7+
__license__ = 'GPL 2.0/LGPL 2.1'
8+
__all__ = (
9+
'dict_to_obj',
10+
'obj_to_dict',
11+
'Wrapper',
12+
)
13+
14+
15+
@python_2_unicode_compatible
16+
class Wrapper(object):
17+
"""Wrapper.
18+
19+
Example:
20+
>>> from django_elasticsearch_dsl_drf.wrappers import DictProxy
21+
>>>
22+
>>> mapping = {
23+
>>> 'country': {
24+
>>> 'name': 'Netherlands',
25+
>>> 'province': {
26+
>>> 'name': 'North Holland',
27+
>>> 'city': {
28+
>>> 'name': 'Amsterdam',
29+
>>> }
30+
>>> }
31+
>>> }
32+
>>> }
33+
>>>
34+
>>> wrapper = dict_to_obj(mapping)
35+
>>> wrapper.country.name
36+
>>> "Netherlands"
37+
>>> wrapper.country.province.name
38+
>>> "North Holland"
39+
>>> wrapper.country.province.city.name
40+
>>> "Amsterdam"
41+
>>> wrapper.as_dict
42+
>>> {
43+
>>> 'country': {
44+
>>> 'name': 'Netherlands',
45+
>>> 'province': {
46+
>>> 'name': 'North Holland',
47+
>>> 'city': {
48+
>>> 'name': 'Amsterdam',
49+
>>> }
50+
>>> }
51+
>>> }
52+
>>> }
53+
>>> str(wrapper)
54+
>>> "Netherlands"
55+
"""
56+
57+
def __str__(self):
58+
for key, item in self.__dict__.items():
59+
if isinstance(item, Wrapper):
60+
return item.__str__()
61+
else:
62+
return item
63+
64+
@property
65+
def as_dict(self):
66+
"""As dict.
67+
68+
:return:
69+
:rtype: dict
70+
"""
71+
return obj_to_dict(self)
72+
73+
@property
74+
def as_json(self):
75+
"""As JSON.
76+
77+
:return:
78+
:rtype: str
79+
"""
80+
return json.dumps(self.as_dict)
81+
82+
83+
def dict_to_obj(mapping):
84+
"""dict to obj mapping.
85+
86+
:param mapping:
87+
:type mapping: dict
88+
:return:
89+
:rtype: :obj:`Wrapper`
90+
"""
91+
wrapper = Wrapper()
92+
93+
for key, item in mapping.items():
94+
if isinstance(item, dict):
95+
setattr(wrapper, key, dict_to_obj(item))
96+
else:
97+
setattr(wrapper, key, item)
98+
return wrapper
99+
100+
101+
def obj_to_dict(obj):
102+
"""Wrapper to dict.
103+
104+
:param obj:
105+
:type obj: `obj`:Wrapper:
106+
:return:
107+
:rtype: dict
108+
"""
109+
mapping = {}
110+
111+
for key, item in obj.__dict__.items():
112+
if isinstance(item, Wrapper):
113+
mapping.update({key: obj_to_dict(item)})
114+
else:
115+
mapping.update({key: item})
116+
117+
return mapping

0 commit comments

Comments
 (0)