Skip to content

Commit 01f7df9

Browse files
Merge pull request #36 from dmm-com/feature/array_group
Added new feature of attribute-type 'array_group'
2 parents 7826570 + a978c88 commit 01f7df9

18 files changed

+1053
-627
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ celerybeat-schedule
9797
.venv
9898
venv/
9999
ENV/
100-
virtualenv-*/
100+
/virtualenv*/
101101

102102
# Spyder project settings
103103
.spyderproject

airone/lib/elasticsearch.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ def make_search_results(results, res, hint_attrs, limit, hint_referral):
727727

728728
ret_attrinfo['type'] = attrinfo['type']
729729
if (attrinfo['type'] == AttrTypeValue['string'] or
730-
attrinfo['type'] == AttrTypeValue['text']):
730+
attrinfo['type'] == AttrTypeValue['text']):
731731

732732
if attrinfo['value']:
733733
ret_attrinfo['value'] = attrinfo['value']
@@ -753,23 +753,23 @@ def make_search_results(results, res, hint_attrs, limit, hint_referral):
753753
if 'value' not in ret_attrinfo:
754754
ret_attrinfo['value'] = []
755755

756-
if attrinfo['type'] == AttrTypeValue['array_string']:
756+
if attrinfo['type'] & AttrTypeValue['named']:
757+
ret_attrinfo['value'].append({
758+
attrinfo['key']: {'id': attrinfo['referral_id'], 'name': attrinfo['value']}
759+
})
760+
761+
elif attrinfo['type'] & AttrTypeValue['string']:
757762
if 'date_value' in attrinfo:
758763
ret_attrinfo['value'].append(attrinfo['date_value'].split('T')[0])
759764
else:
760765
ret_attrinfo['value'].append(attrinfo['value'])
761766

762-
elif attrinfo['type'] == AttrTypeValue['array_object']:
767+
elif attrinfo['type'] & (AttrTypeValue['object'] | AttrTypeValue['group']):
763768
ret_attrinfo['value'].append({
764769
'id': attrinfo['referral_id'],
765770
'name': attrinfo['value']
766771
})
767772

768-
elif attrinfo['type'] == AttrTypeValue['array_named_object']:
769-
ret_attrinfo['value'].append({
770-
attrinfo['key']: {'id': attrinfo['referral_id'], 'name': attrinfo['value']}
771-
})
772-
773773
results['ret_values'].append(ret_info)
774774

775775
return results

airone/lib/types.py

+7
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ class AttrTypeArrNamedObj(with_metaclass(MetaAttrType)):
6161
TYPE = _ATTR_OBJECT_TYPE | _ATTR_NAMED_TYPE | _ATTR_ARRAY_TYPE
6262

6363

64+
class AttrTypeArrGroup(with_metaclass(MetaAttrType)):
65+
NAME = 'array_group'
66+
TYPE = _ATTR_GROUP_TYPE | _ATTR_ARRAY_TYPE
67+
68+
6469
class AttrTypeText(with_metaclass(MetaAttrType)):
6570
NAME = 'textarea'
6671
TYPE = _ATTR_TEXT_TYPE
@@ -88,6 +93,7 @@ class AttrTypeDate(with_metaclass(MetaAttrType)):
8893
AttrTypeArrStr,
8994
AttrTypeArrObj,
9095
AttrTypeArrNamedObj,
96+
AttrTypeArrGroup,
9197
AttrTypeText,
9298
AttrTypeBoolean,
9399
AttrTypeGroup,
@@ -102,6 +108,7 @@ class AttrTypeDate(with_metaclass(MetaAttrType)):
102108
'array_object': AttrTypeArrObj.TYPE,
103109
'array_string': AttrTypeArrStr.TYPE,
104110
'array_named_object': AttrTypeArrNamedObj.TYPE,
111+
'array_group': AttrTypeArrGroup.TYPE,
105112
'text': AttrTypeText.TYPE,
106113
'boolean': AttrTypeBoolean.TYPE,
107114
'group': AttrTypeGroup.TYPE,

api_v1/serializers.py

+6-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from airone.lib.types import AttrTypeValue
22
from entity.models import Entity
3-
from entry.models import Entry
3+
from entry.models import Entry, AttributeValue
44
from group.models import Group
55
from rest_framework import serializers
66
from rest_framework.exceptions import ValidationError
@@ -127,6 +127,10 @@ def validate_named_attr(value):
127127
return sum([[get_entry(r, v) for r in attr.referral.all() if is_entry(r, v)]
128128
for v in value], [])
129129

130+
elif attr.type & AttrTypeValue['group']:
131+
return [x for x in
132+
[AttributeValue.uniform_storable_for_group(v) for v in value] if x]
133+
130134
elif attr.type & AttrTypeValue['string'] or attr.type & AttrTypeValue['text']:
131135
if not isinstance(value, str):
132136
return None
@@ -168,17 +172,7 @@ def validate_named_attr(value):
168172
return None
169173

170174
elif attr.type & AttrTypeValue['group']:
171-
# This means not None but empty referral value
172-
if not value:
173-
return 0
174-
175-
if not isinstance(value, str):
176-
return None
177-
178-
if not Group.objects.filter(name=value).exists():
179-
return None
180-
181-
return str(Group.objects.get(name=value).id)
175+
return AttributeValue.uniform_storable_for_group(value)
182176

183177
return None
184178

api_v1/tests/test_api.py

+25-16
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ def tearDown(self):
3636
def test_post_entry(self):
3737
admin = self.admin_login()
3838

39-
# create referred Entity and Entries
39+
# create referred Entity, Entries and Groups
40+
test_groups = [Group.objects.create(name=x) for x in ['group1', 'group2']]
4041
ref_entity = Entity.objects.create(name='Referred Entity', created_user=admin)
4142
ref_e = []
4243
for index in range(0, 10):
@@ -51,6 +52,7 @@ def test_post_entry(self):
5152
{'name': 'bool', 'type': AttrTypeValue['boolean']},
5253
{'name': 'date', 'type': AttrTypeValue['date']},
5354
{'name': 'group', 'type': AttrTypeValue['group']},
55+
{'name': 'groups', 'type': AttrTypeValue['array_group']},
5456
{'name': 'text', 'type': AttrTypeValue['text']},
5557
{'name': 'vals', 'type': AttrTypeValue['array_string']},
5658
{'name': 'refs', 'type': AttrTypeValue['array_object'], 'ref': ref_entity},
@@ -77,7 +79,8 @@ def test_post_entry(self):
7779
'name': {'name': 'hoge', 'id': 'r-1'},
7880
'bool': False,
7981
'date': '2018-12-31',
80-
'group': Group.objects.create(name='new_group').name,
82+
'group': 'group1',
83+
'groups': ['group1', 'group2'],
8184
'text': 'fuga',
8285
'vals': ['foo', 'bar'],
8386
'refs': ['r-2', 'r-3'],
@@ -99,7 +102,7 @@ def test_post_entry(self):
99102

100103
new_entry = Entry.objects.get(id=ret_data['result'])
101104
self.assertEqual(new_entry.name, 'entry1')
102-
self.assertEqual(new_entry.attrs.count(), 10)
105+
self.assertEqual(new_entry.attrs.count(), len(attr_params))
103106

104107
# checking new_entry is registered to the Elasticsearch
105108
res = self._es.get(index=settings.ES_CONFIG['INDEX'], doc_type='entry', id=new_entry.id)
@@ -114,7 +117,10 @@ def test_post_entry(self):
114117
{'name': 'bool', 'check': lambda v: self.assertEqual(v.boolean, False)},
115118
{'name': 'date', 'check': lambda v: self.assertEqual(v.date, date(2018, 12, 31))},
116119
{'name': 'group', 'check': lambda v: self.assertEqual(
117-
v.value, str(Group.objects.get(name='new_group').id))},
120+
v.value, str(Group.objects.get(name='group1').id))},
121+
{'name': 'groups', 'check': lambda v: self.assertEqual(
122+
[x.value for x in v.data_array.all()], [str(x.id) for x in test_groups]
123+
)},
118124
{'name': 'text', 'check': lambda v: self.assertEqual(v.value, 'fuga')},
119125
{'name': 'vals', 'check': lambda v: self.assertEqual(v.data_array.count(), 2)},
120126
{'name': 'vals', 'check': lambda v: self.assertEqual(
@@ -148,6 +154,7 @@ def test_post_entry(self):
148154
'ref': '',
149155
'name': {},
150156
'group': '',
157+
'groups': [],
151158
'text': '',
152159
'vals': [],
153160
'refs': [],
@@ -166,22 +173,14 @@ def test_post_entry(self):
166173
for attr in new_entry.attrs.filter(is_active=True):
167174
attrv = attr.get_latest_value()
168175

169-
if attr.schema.name == 'val':
176+
if attr.schema.name in ['val', 'group', 'text']:
170177
self.assertEqual(attrv.value, '')
171178
elif attr.schema.name == 'ref':
172179
self.assertIsNone(attrv.referral)
173180
elif attr.schema.name == 'name':
174181
self.assertEqual(attrv.value, '')
175182
self.assertIsNone(attrv.referral)
176-
elif attr.schema.name == 'group':
177-
self.assertEqual(attrv.value, '')
178-
elif attr.schema.name == 'text':
179-
self.assertEqual(attrv.value, '')
180-
elif attr.schema.name == 'vals':
181-
self.assertEqual(attrv.data_array.count(), 0)
182-
elif attr.schema.name == 'refs':
183-
self.assertEqual(attrv.data_array.count(), 0)
184-
elif attr.schema.name == 'names':
183+
elif attr.schema.name in ['vals', 'refs', 'names', 'groups']:
185184
self.assertEqual(attrv.data_array.count(), 0)
186185

187186
def test_edit_entry_by_api(self):
@@ -529,6 +528,7 @@ def test_failed_to_get_entry(self):
529528
def test_get_entry(self):
530529
user = self.admin_login()
531530

531+
test_groups = [Group.objects.create(name=x) for x in ['group1', 'group2']]
532532
ref_entity = Entity.objects.create(name='RefEntity', created_user=user)
533533
ref_entry = Entry.objects.create(name='RefEntry', created_user=user, schema=ref_entity)
534534

@@ -539,6 +539,8 @@ def test_get_entry(self):
539539
'ref': {'type': AttrTypeValue['object'], 'value': ref_entry,
540540
'referral': ref_entity},
541541
'no_str': {'type': AttrTypeValue['string']},
542+
'group': {'type': AttrTypeValue['group'], 'value': test_groups[0]},
543+
'groups': {'type': AttrTypeValue['array_group'], 'value': test_groups},
542544
}
543545
for (name, info) in attr_info.items():
544546
attr = EntityAttr.objects.create(name=name,
@@ -581,7 +583,13 @@ def test_get_entry(self):
581583

582584
entry = Entry.objects.get(name='entry-0', schema__name='hoge')
583585
self.assertEqual(results[0]['id'], entry.id)
586+
587+
# check responded attribute informations
584588
self.assertEqual(len(results[0]['attrs']), entry.attrs.count())
589+
self.assertEqual([x for x in results[0]['attrs'] if x['name'] == 'group'],
590+
[{'name': 'group', 'value': 'group1'}])
591+
self.assertEqual([x for x in results[0]['attrs'] if x['name'] == 'groups'],
592+
[{'name': 'groups', 'value': ['group1', 'group2']}])
585593

586594
# the case to specify only 'entry' parameter
587595
resp = self.client.get('/api/v1/entry', {'entry': 'entry-0'})
@@ -613,12 +621,13 @@ def test_get_entry(self):
613621
self.assertEqual(len(results), 1)
614622
self.assertEqual(results[0]['id'],
615623
Entry.objects.get(name='entry-1', schema__name='hoge').id)
616-
self.assertEqual([x['name'] for x in results[0]['attrs']], ['no_str'])
624+
self.assertEqual(sorted([x['name'] for x in results[0]['attrs']]),
625+
sorted(['no_str', 'group', 'groups']))
617626

618627
resp = self.client.get('/api/v1/entry', {'entry': 'entry-2'})
619628
self.assertEqual(resp.status_code, 200)
620629
self.assertEqual(sorted([x['name'] for x in resp.json()[0]['attrs']]),
621-
sorted(['ref', 'no_str']))
630+
sorted(['ref', 'no_str', 'group', 'groups']))
622631

623632
def test_get_entry_with_only_entity_parameter(self):
624633
user = self.admin_login()

entry/api_v1/views.py

+27-17
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from entry.models import Entry, Attribute
1616
from entity.models import Entity, EntityAttr
1717
from entry.settings import CONFIG
18+
from group.models import Group
1819
from pytz import timezone
1920
from user.models import User
2021
from natsort import natsorted
@@ -164,6 +165,26 @@ def get_attr_referrals(request, attr_id):
164165
"""
165166
This returns entries that target attribute refers to.
166167
"""
168+
169+
def _get_referral_objects(attr, model, query_params={}):
170+
query_name = Q()
171+
172+
keyword = request.GET.get('keyword')
173+
if keyword:
174+
query_name = Q(name__icontains=keyword)
175+
176+
return [{'id': x.id, 'name': x.name} for x in
177+
model.objects.filter(Q(**query_params), query_name)[0:CONFIG.MAX_LIST_REFERRALS]]
178+
179+
def _get_referral_entries(attr):
180+
return _get_referral_objects(attr, Entry, {
181+
'schema__in': [x for x in attr.referral.all()],
182+
'is_active': True
183+
})
184+
185+
def _get_referral_groups(attr):
186+
return _get_referral_objects(attr, Group, {'is_active': True})
187+
167188
if (not Attribute.objects.filter(id=attr_id).exists() and
168189
not EntityAttr.objects.filter(id=attr_id).exists()):
169190
return HttpResponse('Failed to get target attribute(%s)' % attr_id, status=400)
@@ -174,24 +195,13 @@ def get_attr_referrals(request, attr_id):
174195
else:
175196
attr = EntityAttr.objects.get(id=attr_id)
176197

177-
if not attr.type & AttrTypeValue['object']:
198+
if attr.type & AttrTypeValue['object']:
199+
results = _get_referral_entries(attr)
200+
elif attr.type & AttrTypeValue['group']:
201+
results = _get_referral_groups(attr)
202+
else:
178203
return HttpResponse('Target Attribute does not referring type', status=400)
179204

180-
results = []
181-
for referral in attr.referral.all():
182-
keyword = request.GET.get('keyword')
183-
if keyword:
184-
query_name_regex = Q(name__icontains=keyword)
185-
else:
186-
query_name_regex = Q()
187-
188-
results += [{'id': x.id, 'name': x.name}
189-
for x in Entry.objects.filter(Q(schema=referral, is_active=True),
190-
query_name_regex)]
191-
192-
if len(results) > CONFIG.MAX_LIST_REFERRALS:
193-
break
194-
195205
return JsonResponse(
196206
{'results': natsorted(results, key=lambda x: x['name'])[0:CONFIG.MAX_LIST_REFERRALS]})
197207

@@ -216,7 +226,7 @@ def get_entry_history(request, entry_id):
216226
return HttpResponse("Specified entry doesn't exist", status=400)
217227

218228
def json_serial(obj):
219-
if isinstance(obj, ACLBase):
229+
if isinstance(obj, ACLBase) or isinstance(obj, Group):
220230
return {'id': obj.id, 'name': obj.name}
221231
elif isinstance(obj, datetime):
222232
return obj.astimezone(timezone('Asia/Tokyo')).strftime('%b. %d, %Y, %I:%M %p')

0 commit comments

Comments
 (0)