Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7a54d92
Blitz Dataset getQueryString() handles filter by 'image'
will-moore Feb 7, 2017
0bf88d2
api DatasetsView handles ?image=1
will-moore Feb 7, 2017
ec492b8
Blitz Project getQueryString() support filter by 'dataset'
will-moore Feb 7, 2017
cd2ea10
api ProjectsView supports filter by ?dataset=1
will-moore Feb 7, 2017
415c095
url:datasets and url:projects for browsing I->D->P
will-moore Feb 7, 2017
dac376d
Blitz Screen getQueryString() supports filtering by 'plate'
will-moore Feb 7, 2017
0620179
api support filtering /screens/?plate=id and plate/:id/screens
will-moore Feb 7, 2017
b5972a6
Add 'url:screens' to plate json
will-moore Feb 7, 2017
861d645
New test 'test_pdi_parent_urls' in teat_api_containers.py
will-moore Feb 8, 2017
52359aa
Tiny fix to avoid merge conflict
will-moore Feb 24, 2017
304b8e8
Add 'X-OMERO-ApiVersion' = '0.0' to response Headers
will-moore Feb 24, 2017
9f620a5
Update Training/python/Json_Api/Login.py with new urls etc
will-moore Feb 27, 2017
1d3a952
Merge remote-tracking branch 'origin/develop' into api_filter_by_chil…
will-moore Feb 28, 2017
68ba82d
flake8 fix
will-moore Feb 28, 2017
81b3ce8
Fix test_pdi_parent_urls
will-moore Feb 28, 2017
f461940
Blitz Plate.getQueryString() supports filter by 'well'
will-moore Feb 28, 2017
8c27b92
Add support for /wells/:id/plates/
will-moore Feb 28, 2017
9cc3938
Blitz docstring update
will-moore Feb 28, 2017
8f81f9f
Add test 'test_spw_parent_urls'
will-moore Feb 28, 2017
149669e
Remove print from Training Login.py
will-moore Feb 28, 2017
73372cd
Add Json_Api/Login.py to Training test suite
will-moore Feb 28, 2017
65777ad
flake8 fix
will-moore Feb 28, 2017
4d036ed
Blitz rename plink -> projectLinks in Dataset.getQueryString()
will-moore Mar 5, 2017
c42a896
Update comment in urls.py
will-moore Mar 6, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 60 additions & 6 deletions components/tools/OmeroPy/src/omero/gateway/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5732,18 +5732,25 @@ def _getQueryString(cls, opts=None):
Extend base query to handle filtering of Datasets by Projects.
Returns a tuple of (query, clauses, params).
Supported opts: 'project': <project_id> to filter by Project
'image': <image_id> to filter by child Image
'orphaned': <bool>. Filter by 'not in Project'

:param opts: Dictionary of optional parameters.
:return: Tuple of string, list, ParametersI
"""
query, clauses, params = super(
_DatasetWrapper, cls)._getQueryString(opts)
if opts is not None and 'project' in opts:
query += ' join obj.projectLinks plink'
clauses.append('plink.parent.id = :pid')
if opts is None:
opts = {}
if 'project' in opts:
query += ' join obj.projectLinks projectLinks'
clauses.append('projectLinks.parent.id = :pid')
params.add('pid', rlong(opts['project']))
if opts is not None and opts.get('orphaned'):
if 'image' in opts:
query += ' join obj.imageLinks imagelinks'
clauses.append('imagelinks.child.id = :iid')
params.add('iid', rlong(opts['image']))
if opts.get('orphaned'):
clauses.append(
"""
not exists (
Expand Down Expand Up @@ -5781,6 +5788,26 @@ class _ProjectWrapper (BlitzObjectWrapper):
CHILD_WRAPPER_CLASS = 'DatasetWrapper'
PARENT_WRAPPER_CLASS = None

@classmethod
def _getQueryString(cls, opts=None):
"""
Extend base query to handle filtering of Projects by Datasets.
Returns a tuple of (query, clauses, params).
Supported opts: 'dataset': <dataset_id> to filter by Dataset

:param opts: Dictionary of optional parameters.
:return: Tuple of string, list, ParametersI
"""
query, clauses, params = super(
_ProjectWrapper, cls)._getQueryString(opts)
if opts is None:
opts = {}
if 'dataset' in opts:
query += ' join obj.datasetLinks datasetLinks'
clauses.append('datasetLinks.child.id = :dataset_id')
params.add('dataset_id', rlong(opts['dataset']))
return (query, clauses, params)

ProjectWrapper = _ProjectWrapper


Expand All @@ -5794,6 +5821,26 @@ class _ScreenWrapper (BlitzObjectWrapper):
CHILD_WRAPPER_CLASS = 'PlateWrapper'
PARENT_WRAPPER_CLASS = None

@classmethod
def _getQueryString(cls, opts=None):
"""
Extend base query to handle filtering of Screens by Plate.
Returns a tuple of (query, clauses, params).
Supported opts: 'plate': <plate_id> to filter by Plate

:param opts: Dictionary of optional parameters.
:return: Tuple of string, list, ParametersI
"""
query, clauses, params = super(
_ScreenWrapper, cls)._getQueryString(opts)
if opts is None:
opts = {}
if 'plate' in opts:
query += ' join obj.plateLinks plateLinks'
clauses.append('plateLinks.child.id = :plate_id')
params.add('plate_id', rlong(opts['plate']))
return (query, clauses, params)

ScreenWrapper = _ScreenWrapper


Expand Down Expand Up @@ -6011,6 +6058,7 @@ def _getQueryString(cls, opts=None):
Also handles filtering of Plates by Screens.
Returns a tuple of (query, clauses, params).
Supported opts: 'screen': <screen_id> to filter by Screen
'well': <well_id> to filter by Well
'orphaned': <bool>. Filter by 'not in Screen'

:param opts: Dictionary of optional parameters.
Expand All @@ -6024,10 +6072,16 @@ def _getQueryString(cls, opts=None):
# NB: we don't use base _getQueryString.
clauses = []
params = omero.sys.ParametersI()
if opts is not None and 'screen' in opts:
if opts is None:
opts = {}
if 'screen' in opts:
clauses.append('spl.parent.id = :sid')
params.add('sid', rlong(opts['screen']))
if opts is not None and opts.get('orphaned'):
if 'well' in opts:
query += ' join obj.wells wells'
clauses.append('wells.id = :well_id')
params.add('well_id', rlong(opts['well']))
if opts.get('orphaned'):
clauses.append(
"""
not exists (
Expand Down
2 changes: 2 additions & 0 deletions components/tools/OmeroWeb/omeroweb/api/api_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,5 @@
# E.g. /api/v0/
# TODO - need to decide how this is configured, strategy for extending etc.
API_VERSIONS = ('0',)

API_VERSION = '0.0'
11 changes: 9 additions & 2 deletions components/tools/OmeroWeb/omeroweb/api/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import traceback
from django.http import JsonResponse
from functools import update_wrapper
from . import api_settings
from api_exceptions import BadRequestError, \
CreatedObject, \
MethodNotSupportedError, \
Expand Down Expand Up @@ -58,14 +59,20 @@ def __init__(self):
"""Initialise the decorator."""
pass

def create_response(self, response, status=200):
"""Create the Json response and set global headers."""
response = JsonResponse(response, status=status)
response['X-OMERO-ApiVersion'] = api_settings.API_VERSION
return response

def handle_success(self, rv):
"""
Handle successful response from wrapped function.

By default, we simply return a JsonResponse() but this can be
overwritten by subclasses if needed.
"""
return JsonResponse(rv)
return self.create_response(rv)

def handle_error(self, ex, trace):
"""
Expand Down Expand Up @@ -96,7 +103,7 @@ def handle_error(self, ex, trace):
if isinstance(ex, CreatedObject):
status = ex.status
rsp_json = ex.response
return JsonResponse(rsp_json, status=status)
return self.create_response(rsp_json, status=status)

def __call__(self, f):
"""
Expand Down
40 changes: 40 additions & 0 deletions components/tools/OmeroWeb/omeroweb/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@
GET Images in Dataset, using omero-marshal to generate json
"""

api_dataset_projects = url(
r'^v(?P<api_version>%s)/m/datasets/'
'(?P<dataset_id>[0-9]+)/projects/$' % versions,
views.ProjectsView.as_view(),
name='api_dataset_projects')
"""
GET Projects that contain a Dataset, using omero-marshal to generate json
"""

api_image = url(
r'^v(?P<api_version>%s)/m/images/(?P<object_id>[0-9]+)/$' % versions,
views.ImageView.as_view(),
Expand All @@ -130,6 +139,15 @@
Image url to GET or DELETE a single Image
"""

api_image_datasets = url(
r'^v(?P<api_version>%s)/m/images/'
'(?P<image_id>[0-9]+)/datasets/$' % versions,
views.DatasetsView.as_view(),
name='api_image_datasets')
"""
GET Datasets that contain an Image, using omero-marshal to generate json
"""

api_screen = url(
r'^v(?P<api_version>%s)/m/screens/(?P<object_id>[0-9]+)/$' % versions,
views.ScreenView.as_view(),
Expand Down Expand Up @@ -161,6 +179,15 @@
GET Plates in Screen, using omero-marshal to generate json
"""

api_well_plates = url(
r'^v(?P<api_version>%s)/m/wells/'
'(?P<well_id>[0-9]+)/plates/$' % versions,
views.PlatesView.as_view(),
name='api_well_plates')
"""
GET Plates that contain a Well, using omero-marshal to generate json
"""

api_plate = url(
r'^v(?P<api_version>%s)/m/plates/(?P<object_id>[0-9]+)/$' % versions,
views.PlateView.as_view(),
Expand Down Expand Up @@ -240,6 +267,15 @@
Well url to GET or DELETE a single Well
"""

api_plate_screens = url(
r'^v(?P<api_version>%s)/m/plates/'
'(?P<plate_id>[0-9]+)/screens/$' % versions,
views.ScreensView.as_view(),
name='api_plate_screens')
"""
GET Screens that contain a Plate, using omero-marshal to generate json
"""

urlpatterns = patterns(
'',
api_versions,
Expand All @@ -255,11 +291,14 @@
api_dataset,
api_images,
api_dataset_images,
api_dataset_projects,
api_image,
api_image_datasets,
api_screen,
api_screens,
api_plates,
api_screen_plates,
api_well_plates,
api_plate,
api_wells,
api_plate_plateacquisitions,
Expand All @@ -269,4 +308,5 @@
api_plate_wells,
api_plateacquisition_wells,
api_well,
api_plate_screens,
)
55 changes: 55 additions & 0 deletions components/tools/OmeroWeb/omeroweb/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ class DatasetView(ObjectView):
urls = {
'url:images': {'name': 'api_dataset_images',
'kwargs': {'dataset_id': 'OBJECT_ID'}},
'url:projects': {'name': 'api_dataset_projects',
'kwargs': {'dataset_id': 'OBJECT_ID'}},
}


Expand All @@ -234,6 +236,12 @@ class ImageView(ObjectView):

CAN_DELETE = False

# Urls to add to marshalled object. See ProjectsView for more details
urls = {
'url:datasets': {'name': 'api_image_datasets',
'kwargs': {'image_id': 'OBJECT_ID'}},
}

def get_opts(self, request):
"""Add support for load_pixels and load_channels."""
opts = super(ImageView, self).get_opts(request)
Expand Down Expand Up @@ -263,6 +271,8 @@ class PlateView(ObjectView):

# Urls to add to marshalled object. See ProjectsView for more details
urls = {
'url:screens': {'name': 'api_plate_screens',
'kwargs': {'plate_id': 'OBJECT_ID'}},
'url:wells': {'name': 'api_plate_wells',
'kwargs': {'plate_id': 'OBJECT_ID'}},
'url:plateacquisitions': {'name': 'api_plate_plateacquisitions',
Expand Down Expand Up @@ -325,6 +335,12 @@ class WellView(ObjectView):

CAN_DELETE = False

# Urls to add to marshalled object. See ProjectsView for more details
urls = {
'url:plates': {'name': 'api_well_plates',
'kwargs': {'well_id': 'OBJECT_ID'}},
}

def get_opts(self, request):
"""Add support for load_images."""
opts = super(WellView, self).get_opts(request)
Expand Down Expand Up @@ -394,6 +410,14 @@ def get_opts(self, request, **kwargs):
"""Add extra parameters to the opts dict."""
opts = super(ProjectsView, self).get_opts(request, **kwargs)
opts['order_by'] = 'lower(obj.name)'
# at /datasets/:dataset_id/projects/ we have 'dataset_id' in kwargs
if 'dataset_id' in kwargs:
opts['dataset'] = long(kwargs['dataset_id'])
else:
# Filter Projects by child 'dataset'
dataset = getIntOrDefault(request, 'dataset', None)
if dataset is not None:
opts['dataset'] = dataset
return opts

# To add a url to marshalled object add to this dict
Expand Down Expand Up @@ -425,6 +449,13 @@ def get_opts(self, request, **kwargs):
project = getIntOrDefault(request, 'project', None)
if project is not None:
opts['project'] = project
# Filter Datasets by child 'image'
if 'image_id' in kwargs:
opts['image'] = long(kwargs['image_id'])
else:
image = getIntOrDefault(request, 'image', None)
if image is not None:
opts['image'] = image
return opts

# Urls to add to marshalled object. See ProjectsView for more details
Expand All @@ -433,6 +464,8 @@ def get_opts(self, request, **kwargs):
'kwargs': {'dataset_id': 'OBJECT_ID'}},
'url:dataset': {'name': 'api_dataset',
'kwargs': {'object_id': 'OBJECT_ID'}},
'url:projects': {'name': 'api_dataset_projects',
'kwargs': {'dataset_id': 'OBJECT_ID'}},
}


Expand All @@ -445,6 +478,14 @@ def get_opts(self, request, **kwargs):
"""Add extra parameters to the opts dict."""
opts = super(ScreensView, self).get_opts(request, **kwargs)
opts['order_by'] = 'lower(obj.name)'
# at /plate/:plate_id/screens/ we have 'plate_id' in kwargs
if 'plate_id' in kwargs:
opts['plate'] = long(kwargs['plate_id'])
else:
# filter by query /screens/?plate=:id
plate = getIntOrDefault(request, 'plate', None)
if plate is not None:
opts['plate'] = plate
return opts

# Urls to add to marshalled object. See ProjectsView for more details
Expand Down Expand Up @@ -473,10 +514,20 @@ def get_opts(self, request, **kwargs):
screen = getIntOrDefault(request, 'screen', None)
if screen is not None:
opts['screen'] = screen
# Filter Plates by Well
if 'well_id' in kwargs:
opts['well'] = long(kwargs['well_id'])
else:
# filter by query /plates/?well=:id
well = getIntOrDefault(request, 'well', None)
if well is not None:
opts['well'] = well
return opts

# Urls to add to marshalled object. See ProjectsView for more details
urls = {
'url:screens': {'name': 'api_plate_screens',
'kwargs': {'plate_id': 'OBJECT_ID'}},
'url:wells': {'name': 'api_plate_wells',
'kwargs': {'plate_id': 'OBJECT_ID'}},
'url:plate': {'name': 'api_plate',
Expand All @@ -495,6 +546,8 @@ class ImagesView(ObjectsView):
urls = {
'url:image': {'name': 'api_image',
'kwargs': {'object_id': 'OBJECT_ID'}},
'url:datasets': {'name': 'api_image_datasets',
'kwargs': {'image_id': 'OBJECT_ID'}},
}

def get_opts(self, request, **kwargs):
Expand Down Expand Up @@ -566,6 +619,8 @@ class WellsView(ObjectsView):
urls = {
'url:well': {'name': 'api_well',
'kwargs': {'object_id': 'OBJECT_ID'}},
'url:plates': {'name': 'api_well_plates',
'kwargs': {'well_id': 'OBJECT_ID'}},
}

def get_opts(self, request, **kwargs):
Expand Down
Loading