Skip to content

Commit cf3af24

Browse files
committed
Redirect image detail URLS to canonical version
1 parent 248c88c commit cf3af24

File tree

5 files changed

+60
-37
lines changed

5 files changed

+60
-37
lines changed

Diff for: isic/core/tests/test_image_identifier.py

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from django.urls import reverse
2+
import pytest
3+
4+
5+
@pytest.mark.django_db
6+
def test_resolve_isic_id(client, image_factory):
7+
image = image_factory(public=True)
8+
response = client.get(f"/images/{image.isic_id}/")
9+
assert response.status_code == 200
10+
11+
12+
@pytest.mark.django_db
13+
def test_resolve_girder_id(client, image_factory):
14+
image = image_factory(public=True, accession__girder_id="5436e3abbae478396759f0cf")
15+
response = client.get(f"/images/{image.accession.girder_id}/")
16+
assert response.status_code == 301
17+
assert response.url == reverse("core/image-detail", kwargs={"image_identifier": image.isic_id})
18+
19+
20+
@pytest.mark.django_db
21+
def test_resolve_pk(client, image_factory):
22+
image = image_factory(public=True)
23+
response = client.get(f"/images/{image.pk}/")
24+
assert response.status_code == 301
25+
assert response.url == reverse("core/image-detail", kwargs={"image_identifier": image.isic_id})

Diff for: isic/core/tests/test_view_image_detail.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
],
2222
)
2323
def test_core_image_detail(client_, image_, can_see):
24-
r = client_.get(reverse("core/image-detail", args=[image_.pk]))
24+
r = client_.get(reverse("core/image-detail", args=[image_.isic_id]))
2525
assert r.status_code == 200 if can_see else 403
2626

2727

@@ -70,7 +70,7 @@ def detailed_image(
7070

7171
@pytest.mark.django_db
7272
def test_view_image_detail_public(client, detailed_image):
73-
r = client.get(reverse("core/image-detail", args=[detailed_image.pk]))
73+
r = client.get(reverse("core/image-detail", args=[detailed_image.isic_id]))
7474
assert r.status_code == 200
7575
assert set(r.context["sections"].keys()) == {"metadata", "studies"}
7676

@@ -92,7 +92,7 @@ def test_view_image_detail_public(client, detailed_image):
9292
def test_view_image_detail_uploader(client, detailed_image):
9393
client.force_login(detailed_image.accession.cohort.contributor.owners.first())
9494

95-
r = client.get(reverse("core/image-detail", args=[detailed_image.pk]))
95+
r = client.get(reverse("core/image-detail", args=[detailed_image.isic_id]))
9696
assert r.status_code == 200
9797
assert set(r.context["sections"].keys()) == {"metadata", "studies"}
9898

Diff for: isic/core/urls.py

+2-33
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
from django.db.models import Q
2-
from django.http.response import Http404
3-
from django.urls import path, register_converter
1+
from django.urls import path
42
from django.views.generic.base import TemplateView
53

6-
from isic.core.constants import ISIC_ID_REGEX, MONGO_ID_REGEX
7-
from isic.core.models.image import Image
84
from isic.core.views.collections import (
95
collection_create_,
106
collection_create_doi_,
@@ -23,33 +19,6 @@
2319
from isic.core.views.lesion import lesion_detail
2420
from isic.core.views.users import staff_list, user_detail
2521

26-
27-
class ImageIdentifierConverter:
28-
regex = f"([0-9]+|{MONGO_ID_REGEX}|{ISIC_ID_REGEX})"
29-
30-
def to_python(self, value):
31-
if value.isnumeric():
32-
image = Image.objects.filter(pk=value).first()
33-
if image:
34-
return image.isic_id
35-
else:
36-
for approach in [
37-
Q(isic_id=value),
38-
Q(accession__girder_id=value),
39-
Q(aliases__isic=value),
40-
]:
41-
image = Image.objects.filter(approach).order_by().first()
42-
if image:
43-
return image.isic_id
44-
45-
raise Http404
46-
47-
def to_url(self, value):
48-
return value
49-
50-
51-
register_converter(ImageIdentifierConverter, "image-identifier")
52-
5322
urlpatterns = [
5423
path(
5524
"robots.txt",
@@ -92,7 +61,7 @@ def to_url(self, value):
9261
name="core/collection-download-metadata",
9362
),
9463
path(
95-
"images/<image-identifier:isic_id>/",
64+
"images/<str:image_identifier>/",
9665
image_detail,
9766
name="core/image-detail",
9867
),

Diff for: isic/core/views/images.py

+29
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,35 @@
2222
MAX_RELATED_SHOW_FIRST_N = 50
2323

2424

25+
def resolve_image_identifier(view_func):
26+
from django.http import HttpResponsePermanentRedirect
27+
from django.urls import reverse
28+
29+
def wrapper(request, image_identifier):
30+
if image_identifier.startswith("ISIC_"):
31+
return view_func(request, isic_id=image_identifier)
32+
33+
alternative_identifier_filters = [
34+
Q(accession__girder_id=image_identifier),
35+
]
36+
37+
if image_identifier.isdigit():
38+
alternative_identifier_filters.append(Q(pk=image_identifier))
39+
40+
for approach in alternative_identifier_filters:
41+
image = Image.objects.filter(approach).order_by().first()
42+
if image:
43+
redirect_url = reverse(
44+
"core/image-detail", kwargs={"image_identifier": image.isic_id}
45+
)
46+
return HttpResponsePermanentRedirect(redirect_url)
47+
48+
return view_func(request, isic_id=image_identifier)
49+
50+
return wrapper
51+
52+
53+
@resolve_image_identifier
2554
@needs_object_permission("core.view_image", (Image, "isic_id", "isic_id"))
2655
def image_detail(request, isic_id):
2756
image = get_object_or_404(

Diff for: isic/core/views/lesion.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def lesion_detail(request, identifier):
4848
if image.accession.image_type
4949
else None,
5050
"isic_id": image.isic_id,
51-
"image_detail_url": reverse("core/image-detail", args=[image.id]),
51+
"image_detail_url": reverse("core/image-detail", args=[image.isic_id]),
5252
"acquisition_day": image.accession.acquisition_day,
5353
}
5454
for image in images

0 commit comments

Comments
 (0)