Skip to content
9 changes: 9 additions & 0 deletions components/tools/OmeroWeb/omeroweb/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,15 @@ def _save_object(self, request, conn, object_json, **kwargs):
# Therefore we ignore any details for now:
obj.unloadDetails()

# TODO: Unlink children for Projects, Datasets and Screens to avoid
# breaking links. See PR #4930
if hasattr(obj, 'unloadDatasetLinks'):
obj.unloadDatasetLinks()
if hasattr(obj, 'unloadImageLinks'):
obj.unloadImageLinks()
if hasattr(obj, 'unloadPlateLinks'):
obj.unloadPlateLinks()

conn.SERVICE_OPTS.setOmeroGroup(group)
obj = conn.getUpdateService().saveAndReturnObject(obj,
conn.SERVICE_OPTS)
Expand Down
61 changes: 61 additions & 0 deletions components/tools/OmeroWeb/test/integration/test_api_containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
PlateI, \
ProjectI, \
ScreenI, \
TagAnnotationI, \
WellI, \
WellSampleI
from omero.rtypes import rstring, rint
Expand Down Expand Up @@ -410,6 +411,66 @@ def test_screens(self, user1, user_screens):
assert_objects(conn, rsp['data'], user_screens,
dtype="Screen", extra=extra)

def test_screen_plates_update(self, user1, screen_plates):
"""Test update of Screen doesn't break links to Plate."""
conn = get_connection(user1)
user_name = conn.getUser().getName()
django_client = self.new_django_client(user_name, user_name)
version = api_settings.API_VERSIONS[-1]
screen = screen_plates[0]
plate_count = len(screen.linkedPlateList())
screen_url = reverse('api_screen',
kwargs={'api_version': version,
'object_id': screen.id.val})
save_url = reverse('api_save', kwargs={'api_version': version})
# Get Screen, update and save back
rsp = _get_response_json(django_client, screen_url, {})
screen_json = rsp['data']
screen_json['Name'] = 'renamed Screen'
_csrf_put_json(django_client, save_url, screen_json)

# Check Screen has been updated and still has child Plates
scr = conn.getObject('Screen', screen.id.val)
assert scr.getName() == 'renamed Screen'
assert len(list(scr.listChildren())) == plate_count

@pytest.mark.parametrize("dtype", [('project', ProjectI),
('dataset', DatasetI),
('screen', ScreenI)])
def test_container_tags_update(self, user1, dtype):
"""
Test updating a Object without losing linked Tags.

If we load a Object without loading Annotations, then update
and save the Object, we don't want to lose Annotation links
"""
conn = get_connection(user1)
user_name = conn.getUser().getName()
django_client = self.new_django_client(user_name, user_name)

container = dtype[1]()
container.name = rstring('test_container_tags_update')
tag = TagAnnotationI()
tag.textValue = rstring('tag')
container.linkAnnotation(tag)
container = get_update_service(user1).saveAndReturnObject(container)

version = api_settings.API_VERSIONS[-1]
object_url = reverse('api_%s' % dtype[0],
kwargs={'api_version': version,
'object_id': container.id.val})
save_url = reverse('api_save', kwargs={'api_version': version})
# Get container, update and save back
rsp = _get_response_json(django_client, object_url, {})
object_json = rsp['data']
object_json['Name'] = 'renamed container'
_csrf_put_json(django_client, save_url, object_json)

# Check container has been updated and still has annotation links
proj = conn.getObject(dtype[0], container.id.val)
assert proj.getName() == 'renamed container'
assert len(list(proj.listAnnotations())) == 1

def test_spw_urls(self, user1, screen_plates):
"""Test browsing via urls in json /api/->SPW."""
conn = get_connection(user1)
Expand Down
40 changes: 39 additions & 1 deletion components/tools/OmeroWeb/test/integration/test_api_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from django.test import Client
import pytest
from omero.gateway import BlitzGateway
from omero.model import ProjectI, DatasetI
from omero.model import DatasetI, ProjectI
from omero.rtypes import unwrap, rstring
from omero_marshal import get_encoder, OME_SCHEMA_URL

Expand Down Expand Up @@ -600,6 +600,44 @@ def test_project_update(self, user1):
rsp = _get_response_json(django_client, project_url, {})
assert rsp['data']['Description'] == 'New test description update'

@pytest.mark.parametrize("dtype", ['Project', 'Dataset'])
def test_project_datasets_update(self, user1, dtype,
project_hierarchy_user1_group1):
"""
Test updating a Project without losing child Datasets.

If we load a Project without loading Datasets, then update
and save the Project, we don't want to lose Dataset links
"""
conn = get_connection(user1)
user_name = conn.getUser().getName()
django_client = self.new_django_client(user_name, user_name)

if dtype == 'Project':
parent = project_hierarchy_user1_group1[0]
child_count = len(parent.linkedDatasetList())
url_name = 'api_project'
else:
parent = project_hierarchy_user1_group1[0].linkedDatasetList()[0]
child_count = len(parent.linkedImageList())
url_name = 'api_dataset'

version = api_settings.API_VERSIONS[-1]
parent_url = reverse(url_name,
kwargs={'api_version': version,
'object_id': parent.id.val})
save_url = reverse('api_save', kwargs={'api_version': version})
# Get Parent, update and save back
rsp = _get_response_json(django_client, parent_url, {})
parent_json = rsp['data']
parent_json['Name'] = 'renamed %s' % dtype
_csrf_put_json(django_client, save_url, parent_json)

# Check Parent has been updated and still has children linked
parentWrapper = conn.getObject(dtype, parent.id.val)
assert parentWrapper.getName() == 'renamed %s' % dtype
assert len(list(parentWrapper.listChildren())) == child_count

def test_project_delete(self, user1):
conn = get_connection(user1)
user_name = conn.getUser().getName()
Expand Down