forked from 0x2620/pandora
refactor find
This commit is contained in:
parent
41d4e52f84
commit
6e7fe215da
1 changed files with 149 additions and 129 deletions
|
@ -102,6 +102,150 @@ def parse_query(data, user):
|
||||||
# group by only allows sorting by name or number of itmes
|
# group by only allows sorting by name or number of itmes
|
||||||
return query
|
return query
|
||||||
|
|
||||||
|
def get_group(request, query, data):
|
||||||
|
group = {
|
||||||
|
'items': []
|
||||||
|
}
|
||||||
|
items = 'items'
|
||||||
|
item_qs = query['qs']
|
||||||
|
order_by = _order_by_group(query)
|
||||||
|
qs = models.Facet.objects.filter(key=query['group']).filter(item__id__in=item_qs)
|
||||||
|
qs = qs.values('value').annotate(items=Count('id')).order_by(*order_by)
|
||||||
|
|
||||||
|
if 'positions' in query:
|
||||||
|
group['positions'] = {}
|
||||||
|
ids = [j['value'] for j in qs]
|
||||||
|
group['positions'] = utils.get_positions(ids, query['positions'])
|
||||||
|
elif 'range' in data:
|
||||||
|
qs = qs[query['range'][0]:query['range'][1]]
|
||||||
|
group['items'] = [{'name': i['value'], 'items': i[items]} for i in qs]
|
||||||
|
else:
|
||||||
|
group['items'] = qs.count()
|
||||||
|
return group
|
||||||
|
|
||||||
|
def get_position(request, query, data):
|
||||||
|
response = {}
|
||||||
|
qs = _order_query(query['qs'], query['sort'])
|
||||||
|
ids = [j['public_id'] for j in qs.values('public_id')]
|
||||||
|
data['conditions'] = data['conditions'] + {
|
||||||
|
'value': query['position'],
|
||||||
|
'key': query['sort'][0]['key'],
|
||||||
|
'operator': '^'
|
||||||
|
}
|
||||||
|
query = parse_query(data, request.user)
|
||||||
|
qs = _order_query(query['qs'], query['sort'])
|
||||||
|
if qs.count() > 0:
|
||||||
|
response['position'] = utils.get_positions(ids, [qs[0].public_id])[0]
|
||||||
|
return response
|
||||||
|
|
||||||
|
def get_positions(request, query):
|
||||||
|
qs = _order_query(query['qs'], query['sort'])
|
||||||
|
ids = list(qs.values_list('public_id', flat=True))
|
||||||
|
return utils.get_positions(ids, query['positions'])
|
||||||
|
|
||||||
|
def is_editable(request, item):
|
||||||
|
if request.user.is_anonymous():
|
||||||
|
return False
|
||||||
|
if not hasattr(request, 'user_group_names'):
|
||||||
|
request.user_group_names = {g.name for g in request.user.groups.all()}
|
||||||
|
if request.user.profile.capability('canEditMetadata') or \
|
||||||
|
request.user.is_staff or \
|
||||||
|
item.get('user') == request.user.username or \
|
||||||
|
set(item.get('groups', [])) & request.user_group_names:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_clips(query, qs):
|
||||||
|
n = qs.count()
|
||||||
|
if n > query['clip_items']:
|
||||||
|
num = query['clip_items']
|
||||||
|
clips = []
|
||||||
|
step = int(n / (num + 1))
|
||||||
|
i = step
|
||||||
|
while i <= (n - step) and i < n and len(clips) < num:
|
||||||
|
clips.append(qs[i])
|
||||||
|
i += step
|
||||||
|
else:
|
||||||
|
clips = qs
|
||||||
|
return [c.json(query['clip_keys'], query['clip_filter']) for c in clips]
|
||||||
|
|
||||||
|
def only_p_sums(request, query, m):
|
||||||
|
r = {}
|
||||||
|
for p in query['keys']:
|
||||||
|
if p == 'accessed':
|
||||||
|
r[p] = m.sort.accessed or ''
|
||||||
|
elif p == 'editable':
|
||||||
|
r[p] = is_editable(request, m.json)
|
||||||
|
elif p in item_sort_keys:
|
||||||
|
r[p] = getattr(m.sort, p)
|
||||||
|
else:
|
||||||
|
r[p] = m.json.get(p)
|
||||||
|
if 'clip_qs' in query:
|
||||||
|
r['clips'] = get_clips(query, query['clip_qs'].filter(item=m))
|
||||||
|
return r
|
||||||
|
|
||||||
|
def only_p(request, query, m):
|
||||||
|
r = {}
|
||||||
|
if m:
|
||||||
|
if not isinstance(m, dict):
|
||||||
|
m = json.loads(m, object_hook=oxdjango.fields.from_json)
|
||||||
|
for p in query['keys']:
|
||||||
|
if p == 'editable':
|
||||||
|
r[p] = is_editable(request, m)
|
||||||
|
else:
|
||||||
|
r[p] = m.get(p)
|
||||||
|
if 'clip_qs' in query:
|
||||||
|
r['clips'] = get_clips(query['clip_qs'].filter(item__public_id=m['id']))
|
||||||
|
return r
|
||||||
|
|
||||||
|
item_sort_keys = {
|
||||||
|
'accessed', 'modified', 'timesaccessed',
|
||||||
|
'numberofannotations', 'numberoffiles', 'numberofdocuments'
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_items(request, query):
|
||||||
|
items = []
|
||||||
|
qs = _order_query(query['qs'], query['sort'])
|
||||||
|
qs = qs[query['range'][0]:query['range'][1]]
|
||||||
|
# items = [m.get_json(_p) for m in qs]
|
||||||
|
if any(p for p in query['keys'] if p in item_sort_keys):
|
||||||
|
qs = qs.select_related()
|
||||||
|
items = [only_p_sums(request, query, m) for m in qs]
|
||||||
|
else:
|
||||||
|
items = [only_p(request, query, m['json']) for m in qs.values('json')]
|
||||||
|
return items
|
||||||
|
|
||||||
|
def get_stats(request, query):
|
||||||
|
stats = {}
|
||||||
|
items = query['qs']
|
||||||
|
files = File.objects.filter(item__in=items).filter(selected=True).filter(size__gt=0)
|
||||||
|
r = files.aggregate(
|
||||||
|
Sum('duration'),
|
||||||
|
Sum('pixels'),
|
||||||
|
Sum('size')
|
||||||
|
)
|
||||||
|
totals = [
|
||||||
|
i['id']
|
||||||
|
for i in settings.CONFIG['totals']
|
||||||
|
if 'capability' not in i or has_capability(request.user, i['capability'])
|
||||||
|
]
|
||||||
|
if 'duration' in totals:
|
||||||
|
stats['duration'] = r['duration__sum']
|
||||||
|
if 'files' in totals:
|
||||||
|
stats['files'] = files.count()
|
||||||
|
if 'items' in totals:
|
||||||
|
stats['items'] = items.count()
|
||||||
|
if 'pixels' in totals:
|
||||||
|
stats['pixels'] = r['pixels__sum']
|
||||||
|
if 'runtime' in totals:
|
||||||
|
stats['runtime'] = items.aggregate(Sum('sort__runtime'))['sort__runtime__sum'] or 0
|
||||||
|
if 'size' in totals:
|
||||||
|
stats['size'] = r['size__sum']
|
||||||
|
for key in ('runtime', 'duration', 'pixels', 'size'):
|
||||||
|
if key in totals and stats[key] is None:
|
||||||
|
stats[key] = 0
|
||||||
|
return stats
|
||||||
|
|
||||||
def find(request, data):
|
def find(request, data):
|
||||||
'''
|
'''
|
||||||
Finds items for a given query
|
Finds items for a given query
|
||||||
|
@ -177,142 +321,18 @@ def find(request, data):
|
||||||
|
|
||||||
response = json_response({})
|
response = json_response({})
|
||||||
if 'group' in query:
|
if 'group' in query:
|
||||||
response['data']['items'] = []
|
response['data'] = get_group(request, query, data)
|
||||||
items = 'items'
|
|
||||||
item_qs = query['qs']
|
|
||||||
order_by = _order_by_group(query)
|
|
||||||
qs = models.Facet.objects.filter(key=query['group']).filter(item__id__in=item_qs)
|
|
||||||
qs = qs.values('value').annotate(items=Count('id')).order_by(*order_by)
|
|
||||||
|
|
||||||
if 'positions' in query:
|
|
||||||
response['data']['positions'] = {}
|
|
||||||
ids = [j['value'] for j in qs]
|
|
||||||
response['data']['positions'] = utils.get_positions(ids, query['positions'])
|
|
||||||
elif 'range' in data:
|
|
||||||
qs = qs[query['range'][0]:query['range'][1]]
|
|
||||||
response['data']['items'] = [{'name': i['value'], 'items': i[items]} for i in qs]
|
|
||||||
else:
|
|
||||||
response['data']['items'] = qs.count()
|
|
||||||
elif 'position' in query:
|
elif 'position' in query:
|
||||||
qs = _order_query(query['qs'], query['sort'])
|
response['data'] = get_position(request, query, data)
|
||||||
ids = [j['public_id'] for j in qs.values('public_id')]
|
|
||||||
data['conditions'] = data['conditions'] + {
|
|
||||||
'value': query['position'],
|
|
||||||
'key': query['sort'][0]['key'],
|
|
||||||
'operator': '^'
|
|
||||||
}
|
|
||||||
query = parse_query(data, request.user)
|
|
||||||
qs = _order_query(query['qs'], query['sort'])
|
|
||||||
if qs.count() > 0:
|
|
||||||
response['data']['position'] = utils.get_positions(ids, [qs[0].public_id])[0]
|
|
||||||
elif 'positions' in query:
|
elif 'positions' in query:
|
||||||
qs = _order_query(query['qs'], query['sort'])
|
response['data']['positions'] = get_positions(request, query)
|
||||||
ids = list(qs.values_list('public_id', flat=True))
|
|
||||||
response['data']['positions'] = utils.get_positions(ids, query['positions'])
|
|
||||||
elif 'keys' in query:
|
elif 'keys' in query:
|
||||||
response['data']['items'] = []
|
response['data']['items'] = get_items(request, query)
|
||||||
qs = _order_query(query['qs'], query['sort'])
|
|
||||||
_p = query['keys']
|
|
||||||
|
|
||||||
def get_clips(qs):
|
|
||||||
n = qs.count()
|
|
||||||
if n > query['clip_items']:
|
|
||||||
num = query['clip_items']
|
|
||||||
clips = []
|
|
||||||
step = int(n / (num + 1))
|
|
||||||
i = step
|
|
||||||
while i <= (n - step) and i < n and len(clips) < num:
|
|
||||||
clips.append(qs[i])
|
|
||||||
i += step
|
|
||||||
else:
|
|
||||||
clips = qs
|
|
||||||
return [c.json(query['clip_keys'], query['clip_filter']) for c in clips]
|
|
||||||
|
|
||||||
sort_keys = {
|
|
||||||
'accessed', 'modified', 'timesaccessed',
|
|
||||||
'numberofannotations', 'numberoffiles', 'numberofdocuments'
|
|
||||||
}
|
|
||||||
|
|
||||||
groups = {g.name for g in request.user.groups.all()}
|
|
||||||
|
|
||||||
def is_editable(item):
|
|
||||||
if request.user.is_anonymous():
|
|
||||||
return False
|
|
||||||
if request.user.profile.capability('canEditMetadata') or \
|
|
||||||
request.user.is_staff or \
|
|
||||||
item.get('user') == request.user.username or \
|
|
||||||
set(item.get('groups', [])) & groups:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def only_p_sums(m):
|
|
||||||
r = {}
|
|
||||||
for p in _p:
|
|
||||||
if p == 'accessed':
|
|
||||||
r[p] = m.sort.accessed or ''
|
|
||||||
elif p == 'editable':
|
|
||||||
r[p] = is_editable(m.json)
|
|
||||||
elif p in sort_keys:
|
|
||||||
r[p] = getattr(m.sort, p)
|
|
||||||
else:
|
|
||||||
r[p] = m.json.get(p)
|
|
||||||
if 'clip_qs' in query:
|
|
||||||
r['clips'] = get_clips(query['clip_qs'].filter(item=m))
|
|
||||||
return r
|
|
||||||
|
|
||||||
def only_p(m):
|
|
||||||
r = {}
|
|
||||||
if m:
|
|
||||||
if not isinstance(m, dict):
|
|
||||||
m = json.loads(m, object_hook=oxdjango.fields.from_json)
|
|
||||||
for p in _p:
|
|
||||||
if p == 'editable':
|
|
||||||
r[p] = is_editable(m)
|
|
||||||
else:
|
|
||||||
r[p] = m.get(p)
|
|
||||||
if 'clip_qs' in query:
|
|
||||||
r['clips'] = get_clips(query['clip_qs'].filter(item__public_id=m['id']))
|
|
||||||
return r
|
|
||||||
qs = qs[query['range'][0]:query['range'][1]]
|
|
||||||
# response['data']['items'] = [m.get_json(_p) for m in qs]
|
|
||||||
if any(p for p in _p if p in sort_keys):
|
|
||||||
qs = qs.select_related()
|
|
||||||
response['data']['items'] = [only_p_sums(m) for m in qs]
|
|
||||||
else:
|
|
||||||
response['data']['items'] = [only_p(m['json']) for m in qs.values('json')]
|
|
||||||
|
|
||||||
else: # otherwise stats
|
else: # otherwise stats
|
||||||
items = query['qs']
|
response['data'] = get_stats(request, query)
|
||||||
files = File.objects.filter(item__in=items).filter(selected=True).filter(size__gt=0)
|
|
||||||
r = files.aggregate(
|
|
||||||
Sum('duration'),
|
|
||||||
Sum('pixels'),
|
|
||||||
Sum('size')
|
|
||||||
)
|
|
||||||
totals = [
|
|
||||||
i['id']
|
|
||||||
for i in settings.CONFIG['totals']
|
|
||||||
if 'capability' not in i or has_capability(request.user, i['capability'])
|
|
||||||
]
|
|
||||||
if 'duration' in totals:
|
|
||||||
response['data']['duration'] = r['duration__sum']
|
|
||||||
if 'files' in totals:
|
|
||||||
response['data']['files'] = files.count()
|
|
||||||
if 'items' in totals:
|
|
||||||
response['data']['items'] = items.count()
|
|
||||||
if 'pixels' in totals:
|
|
||||||
response['data']['pixels'] = r['pixels__sum']
|
|
||||||
if 'runtime' in totals:
|
|
||||||
response['data']['runtime'] = items.aggregate(Sum('sort__runtime'))['sort__runtime__sum'] or 0
|
|
||||||
if 'size' in totals:
|
|
||||||
response['data']['size'] = r['size__sum']
|
|
||||||
for key in ('runtime', 'duration', 'pixels', 'size'):
|
|
||||||
if key in totals and response['data'][key] is None:
|
|
||||||
response['data'][key] = 0
|
|
||||||
return render_to_json_response(response)
|
return render_to_json_response(response)
|
||||||
actions.register(find)
|
actions.register(find)
|
||||||
|
|
||||||
|
|
||||||
def autocomplete(request, data):
|
def autocomplete(request, data):
|
||||||
'''
|
'''
|
||||||
Returns autocomplete strings for a given item key and search string
|
Returns autocomplete strings for a given item key and search string
|
||||||
|
|
Loading…
Reference in a new issue