Handle server-side pagination in /bcloud/texture-libraries
We keep looping over the pages until the last page is hit. As a result, we can't forward the HTTP headers from Eve to the client.
This commit is contained in:
parent
e0b7bcb6b7
commit
0caa2df964
@ -3,17 +3,18 @@ import logging
|
|||||||
from flask import Blueprint, request, current_app, g
|
from flask import Blueprint, request, current_app, g
|
||||||
from eve.methods.get import get
|
from eve.methods.get import get
|
||||||
from eve.utils import config as eve_config
|
from eve.utils import config as eve_config
|
||||||
|
from werkzeug.datastructures import MultiDict
|
||||||
|
from werkzeug.exceptions import InternalServerError
|
||||||
|
|
||||||
from application import utils
|
from application import utils
|
||||||
from application.utils.authorization import require_login
|
from application.utils.authorization import require_login
|
||||||
|
|
||||||
|
TL_PROJECTION = utils.dumps({'name': 1, 'url': 1, 'permissions': 1,})
|
||||||
|
TL_SORT = utils.dumps([('name', 1)])
|
||||||
|
|
||||||
TEXTURE_LIBRARY_QUERY_ARGS = {
|
TEXTURE_LIBRARY_QUERY_ARGS = {
|
||||||
eve_config.QUERY_PROJECTION: utils.dumps({
|
eve_config.QUERY_PROJECTION: TL_PROJECTION,
|
||||||
'name': 1,
|
eve_config.QUERY_SORT: TL_SORT,
|
||||||
'url': 1,
|
|
||||||
'permissions': 1,
|
|
||||||
}),
|
|
||||||
eve_config.QUERY_SORT: utils.dumps([('name', 1)]),
|
|
||||||
'max_results': 'null', # this needs to be there, or we get a KeyError.
|
'max_results': 'null', # this needs to be there, or we get a KeyError.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,29 +22,62 @@ blueprint = Blueprint('blender_cloud', __name__)
|
|||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def keep_fetching_texture_libraries(proj_filter):
|
||||||
|
|
||||||
|
groups = g.current_user['groups']
|
||||||
|
user_id = g.current_user['user_id']
|
||||||
|
|
||||||
|
page = 1
|
||||||
|
max_page = float('inf')
|
||||||
|
|
||||||
|
while page <= max_page:
|
||||||
|
request.args.setlist(eve_config.QUERY_PAGE, [page])
|
||||||
|
|
||||||
|
result, _, _, status, _ = get(
|
||||||
|
'projects',
|
||||||
|
{'$or': [
|
||||||
|
{'user': user_id},
|
||||||
|
{'permissions.groups.group': {'$in': groups}},
|
||||||
|
{'permissions.world': 'GET'}
|
||||||
|
]})
|
||||||
|
|
||||||
|
if status != 200:
|
||||||
|
log.warning('Error fetching texture libraries: %s', result)
|
||||||
|
raise InternalServerError('Error fetching texture libraries')
|
||||||
|
|
||||||
|
for proj in result['_items']:
|
||||||
|
if proj_filter(proj):
|
||||||
|
yield proj
|
||||||
|
|
||||||
|
# Compute the last page number we should query.
|
||||||
|
meta = result['_meta']
|
||||||
|
max_page = meta['total'] // meta['max_results']
|
||||||
|
if meta['total'] % meta['max_results'] > 0:
|
||||||
|
max_page += 1
|
||||||
|
|
||||||
|
page += 1
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route('/texture-libraries')
|
@blueprint.route('/texture-libraries')
|
||||||
@require_login()
|
@require_login()
|
||||||
def texture_libraries():
|
def texture_libraries():
|
||||||
# Use Eve method so that we get filtering on permissions for free.
|
# Use Eve method so that we get filtering on permissions for free.
|
||||||
# This gives all the projects that contain the required node types.
|
# This gives all the projects that contain the required node types.
|
||||||
request.args = TEXTURE_LIBRARY_QUERY_ARGS
|
|
||||||
groups = g.current_user['groups']
|
|
||||||
|
|
||||||
result, _, _, status, headers = get(
|
request.args = MultiDict(request.args) # allow changes; it's an ImmutableMultiDict by default.
|
||||||
'projects',
|
request.args.setlist(eve_config.QUERY_PROJECTION, [TL_PROJECTION])
|
||||||
{'$or': [
|
request.args.setlist(eve_config.QUERY_SORT, [TL_SORT])
|
||||||
{'permissions.groups.group': {'$in': groups}},
|
|
||||||
{'permissions.world': 'GET'}
|
|
||||||
]})
|
|
||||||
|
|
||||||
if status == 200:
|
# Construct eve-like response.
|
||||||
# Filter those projects that don't contain a top-level texture or group_texture node.
|
projects = list(keep_fetching_texture_libraries(has_texture_node))
|
||||||
result['_items'] = [proj for proj in result['_items']
|
result = {'_items': projects,
|
||||||
if has_texture_node(proj)]
|
'_meta': {
|
||||||
|
'max_results': len(projects),
|
||||||
|
'page': 1,
|
||||||
|
'total': len(projects),
|
||||||
|
}}
|
||||||
|
|
||||||
resp = utils.jsonify(result)
|
return utils.jsonify(result)
|
||||||
resp.headers.extend(headers)
|
|
||||||
return resp, status
|
|
||||||
|
|
||||||
|
|
||||||
def has_texture_node(proj):
|
def has_texture_node(proj):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user