We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Update to Django 2.2
- [ ] Check that all Django apps support 2.2

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `app/grandchallenge/serving/views.py`
Content:
```
1 import os
2 import posixpath
3 import re
4 
5 from django.conf import settings
6 from django.core.files import File
7 from django.core.files.storage import DefaultStorage
8 from django.http import Http404, HttpResponse
9 from django.shortcuts import get_object_or_404
10 from django.utils._os import safe_join
11 from rest_framework.authentication import TokenAuthentication
12 from rest_framework.exceptions import AuthenticationFailed
13 
14 from grandchallenge.cases.models import Image
15 from grandchallenge.challenges.models import Challenge
16 from grandchallenge.core.storage import ProtectedS3Storage
17 from grandchallenge.evaluation.models import Submission
18 from grandchallenge.serving.api import serve_file
19 from grandchallenge.serving.permissions import (
20     can_access,
21     user_can_download_image,
22     user_can_download_submission,
23 )
24 
25 
26 def serve_fullpath(*, fullpath):
27     storage = DefaultStorage()
28 
29     if not (os.path.abspath(fullpath) == fullpath) or not storage.exists(
30         fullpath
31     ):
32         raise Http404("File not found.")
33 
34     try:
35         f = storage.open(fullpath, "rb")
36         file = File(f)
37         return serve_file(file, save_as=True)
38     except IOError:
39         raise Http404("File not found.")
40 
41 
42 def protected_storage_redirect(*, name):
43     # Get the storage with the internal redirect and auth. This will prepend
44     # settings.PROTECTED_S3_STORAGE_KWARGS['endpoint_url'] to the url
45     storage = ProtectedS3Storage(internal=True)
46 
47     if not storage.exists(name=name):
48         raise Http404("File not found.")
49 
50     url = storage.url(name=name)
51 
52     # Now strip the endpoint_url
53     external_url = re.match(
54         f"^{settings.PROTECTED_S3_STORAGE_KWARGS['endpoint_url']}(.*)$", url
55     ).group(1)
56 
57     response = HttpResponse()
58     response["X-Accel-Redirect"] = external_url
59 
60     return response
61 
62 
63 def serve_folder(request, *, challenge_name=None, folder=None, path):
64     """
65     Serve static files in a folder.
66 
67     If the file is in a challenge folder, then the subfolders of this challenge
68     will be checked for permissions, see `can_access`.
69 
70     If the challenge_short_name is not set, then the folder must be set.
71     ALL FILES IN THIS FOLDER WILL BE AVAILABLE TO DOWNLOAD.
72     """
73     path = posixpath.normpath(path).lstrip("/")
74 
75     if challenge_name:
76         if folder:
77             raise AttributeError("Only challenge_name or folder should be set")
78 
79         challenge = get_object_or_404(
80             Challenge, short_name__iexact=challenge_name
81         )
82 
83         document_root = safe_join(settings.MEDIA_ROOT, challenge.short_name)
84         fullpath = safe_join(document_root, path)
85         allowed = can_access(
86             request.user,
87             fullpath[len(document_root) :].lstrip("/"),
88             challenge=challenge,
89         )
90     elif folder:
91         document_root = safe_join(settings.MEDIA_ROOT, folder)
92         fullpath = safe_join(document_root, path)
93         allowed = True
94     else:
95         raise AttributeError("challenge_name or folder must be set")
96 
97     if not allowed:
98         raise Http404("File not found.")
99 
100     return serve_fullpath(fullpath=fullpath)
101 
102 
103 def serve_images(request, *, pk, path):
104     document_root = safe_join(f"/{settings.IMAGE_FILES_SUBDIRECTORY}", pk)
105     path = posixpath.normpath(path).lstrip("/")
106     name = safe_join(document_root, path)
107 
108     try:
109         image = Image.objects.get(pk=pk)
110     except Image.DoesNotExist:
111         raise Http404("File not found.")
112 
113     try:
114         user, _ = TokenAuthentication().authenticate(request)
115     except (AuthenticationFailed, TypeError):
116         user = request.user
117 
118     if user_can_download_image(user=user, image=image):
119         return protected_storage_redirect(name=name)
120 
121     raise Http404("File not found.")
122 
123 
124 def serve_submissions(request, *, submission_pk, **_):
125     try:
126         submission = Submission.objects.get(pk=submission_pk)
127     except Submission.DoesNotExist:
128         raise Http404("File not found.")
129 
130     if user_can_download_submission(user=request.user, submission=submission):
131         return protected_storage_redirect(name=submission.file.name)
132 
133     raise Http404("File not found.")
134
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/app/grandchallenge/serving/views.py b/app/grandchallenge/serving/views.py
--- a/app/grandchallenge/serving/views.py
+++ b/app/grandchallenge/serving/views.py
@@ -101,7 +101,7 @@
 
 
 def serve_images(request, *, pk, path):
-    document_root = safe_join(f"/{settings.IMAGE_FILES_SUBDIRECTORY}", pk)
+    document_root = safe_join(f"/{settings.IMAGE_FILES_SUBDIRECTORY}", str(pk))
     path = posixpath.normpath(path).lstrip("/")
     name = safe_join(document_root, path)

{"golden_diff": "diff --git a/app/grandchallenge/serving/views.py b/app/grandchallenge/serving/views.py\n--- a/app/grandchallenge/serving/views.py\n+++ b/app/grandchallenge/serving/views.py\n@@ -101,7 +101,7 @@\n \n \n def serve_images(request, *, pk, path):\n-    document_root = safe_join(f\"/{settings.IMAGE_FILES_SUBDIRECTORY}\", pk)\n+    document_root = safe_join(f\"/{settings.IMAGE_FILES_SUBDIRECTORY}\", str(pk))\n     path = posixpath.normpath(path).lstrip(\"/\")\n     name = safe_join(document_root, path)\n", "issue": "Update to Django 2.2\n- [ ] Check that all Django apps support 2.2\n", "before_files": [{"content": "import os\nimport posixpath\nimport re\n\nfrom django.conf import settings\nfrom django.core.files import File\nfrom django.core.files.storage import DefaultStorage\nfrom django.http import Http404, HttpResponse\nfrom django.shortcuts import get_object_or_404\nfrom django.utils._os import safe_join\nfrom rest_framework.authentication import TokenAuthentication\nfrom rest_framework.exceptions import AuthenticationFailed\n\nfrom grandchallenge.cases.models import Image\nfrom grandchallenge.challenges.models import Challenge\nfrom grandchallenge.core.storage import ProtectedS3Storage\nfrom grandchallenge.evaluation.models import Submission\nfrom grandchallenge.serving.api import serve_file\nfrom grandchallenge.serving.permissions import (\n    can_access,\n    user_can_download_image,\n    user_can_download_submission,\n)\n\n\ndef serve_fullpath(*, fullpath):\n    storage = DefaultStorage()\n\n    if not (os.path.abspath(fullpath) == fullpath) or not storage.exists(\n        fullpath\n    ):\n        raise Http404(\"File not found.\")\n\n    try:\n        f = storage.open(fullpath, \"rb\")\n        file = File(f)\n        return serve_file(file, save_as=True)\n    except IOError:\n        raise Http404(\"File not found.\")\n\n\ndef protected_storage_redirect(*, name):\n    # Get the storage with the internal redirect and auth. This will prepend\n    # settings.PROTECTED_S3_STORAGE_KWARGS['endpoint_url'] to the url\n    storage = ProtectedS3Storage(internal=True)\n\n    if not storage.exists(name=name):\n        raise Http404(\"File not found.\")\n\n    url = storage.url(name=name)\n\n    # Now strip the endpoint_url\n    external_url = re.match(\n        f\"^{settings.PROTECTED_S3_STORAGE_KWARGS['endpoint_url']}(.*)$\", url\n    ).group(1)\n\n    response = HttpResponse()\n    response[\"X-Accel-Redirect\"] = external_url\n\n    return response\n\n\ndef serve_folder(request, *, challenge_name=None, folder=None, path):\n    \"\"\"\n    Serve static files in a folder.\n\n    If the file is in a challenge folder, then the subfolders of this challenge\n    will be checked for permissions, see `can_access`.\n\n    If the challenge_short_name is not set, then the folder must be set.\n    ALL FILES IN THIS FOLDER WILL BE AVAILABLE TO DOWNLOAD.\n    \"\"\"\n    path = posixpath.normpath(path).lstrip(\"/\")\n\n    if challenge_name:\n        if folder:\n            raise AttributeError(\"Only challenge_name or folder should be set\")\n\n        challenge = get_object_or_404(\n            Challenge, short_name__iexact=challenge_name\n        )\n\n        document_root = safe_join(settings.MEDIA_ROOT, challenge.short_name)\n        fullpath = safe_join(document_root, path)\n        allowed = can_access(\n            request.user,\n            fullpath[len(document_root) :].lstrip(\"/\"),\n            challenge=challenge,\n        )\n    elif folder:\n        document_root = safe_join(settings.MEDIA_ROOT, folder)\n        fullpath = safe_join(document_root, path)\n        allowed = True\n    else:\n        raise AttributeError(\"challenge_name or folder must be set\")\n\n    if not allowed:\n        raise Http404(\"File not found.\")\n\n    return serve_fullpath(fullpath=fullpath)\n\n\ndef serve_images(request, *, pk, path):\n    document_root = safe_join(f\"/{settings.IMAGE_FILES_SUBDIRECTORY}\", pk)\n    path = posixpath.normpath(path).lstrip(\"/\")\n    name = safe_join(document_root, path)\n\n    try:\n        image = Image.objects.get(pk=pk)\n    except Image.DoesNotExist:\n        raise Http404(\"File not found.\")\n\n    try:\n        user, _ = TokenAuthentication().authenticate(request)\n    except (AuthenticationFailed, TypeError):\n        user = request.user\n\n    if user_can_download_image(user=user, image=image):\n        return protected_storage_redirect(name=name)\n\n    raise Http404(\"File not found.\")\n\n\ndef serve_submissions(request, *, submission_pk, **_):\n    try:\n        submission = Submission.objects.get(pk=submission_pk)\n    except Submission.DoesNotExist:\n        raise Http404(\"File not found.\")\n\n    if user_can_download_submission(user=request.user, submission=submission):\n        return protected_storage_redirect(name=submission.file.name)\n\n    raise Http404(\"File not found.\")\n", "path": "app/grandchallenge/serving/views.py"}], "after_files": [{"content": "import os\nimport posixpath\nimport re\n\nfrom django.conf import settings\nfrom django.core.files import File\nfrom django.core.files.storage import DefaultStorage\nfrom django.http import Http404, HttpResponse\nfrom django.shortcuts import get_object_or_404\nfrom django.utils._os import safe_join\nfrom rest_framework.authentication import TokenAuthentication\nfrom rest_framework.exceptions import AuthenticationFailed\n\nfrom grandchallenge.cases.models import Image\nfrom grandchallenge.challenges.models import Challenge\nfrom grandchallenge.core.storage import ProtectedS3Storage\nfrom grandchallenge.evaluation.models import Submission\nfrom grandchallenge.serving.api import serve_file\nfrom grandchallenge.serving.permissions import (\n    can_access,\n    user_can_download_image,\n    user_can_download_submission,\n)\n\n\ndef serve_fullpath(*, fullpath):\n    storage = DefaultStorage()\n\n    if not (os.path.abspath(fullpath) == fullpath) or not storage.exists(\n        fullpath\n    ):\n        raise Http404(\"File not found.\")\n\n    try:\n        f = storage.open(fullpath, \"rb\")\n        file = File(f)\n        return serve_file(file, save_as=True)\n    except IOError:\n        raise Http404(\"File not found.\")\n\n\ndef protected_storage_redirect(*, name):\n    # Get the storage with the internal redirect and auth. This will prepend\n    # settings.PROTECTED_S3_STORAGE_KWARGS['endpoint_url'] to the url\n    storage = ProtectedS3Storage(internal=True)\n\n    if not storage.exists(name=name):\n        raise Http404(\"File not found.\")\n\n    url = storage.url(name=name)\n\n    # Now strip the endpoint_url\n    external_url = re.match(\n        f\"^{settings.PROTECTED_S3_STORAGE_KWARGS['endpoint_url']}(.*)$\", url\n    ).group(1)\n\n    response = HttpResponse()\n    response[\"X-Accel-Redirect\"] = external_url\n\n    return response\n\n\ndef serve_folder(request, *, challenge_name=None, folder=None, path):\n    \"\"\"\n    Serve static files in a folder.\n\n    If the file is in a challenge folder, then the subfolders of this challenge\n    will be checked for permissions, see `can_access`.\n\n    If the challenge_short_name is not set, then the folder must be set.\n    ALL FILES IN THIS FOLDER WILL BE AVAILABLE TO DOWNLOAD.\n    \"\"\"\n    path = posixpath.normpath(path).lstrip(\"/\")\n\n    if challenge_name:\n        if folder:\n            raise AttributeError(\"Only challenge_name or folder should be set\")\n\n        challenge = get_object_or_404(\n            Challenge, short_name__iexact=challenge_name\n        )\n\n        document_root = safe_join(settings.MEDIA_ROOT, challenge.short_name)\n        fullpath = safe_join(document_root, path)\n        allowed = can_access(\n            request.user,\n            fullpath[len(document_root) :].lstrip(\"/\"),\n            challenge=challenge,\n        )\n    elif folder:\n        document_root = safe_join(settings.MEDIA_ROOT, folder)\n        fullpath = safe_join(document_root, path)\n        allowed = True\n    else:\n        raise AttributeError(\"challenge_name or folder must be set\")\n\n    if not allowed:\n        raise Http404(\"File not found.\")\n\n    return serve_fullpath(fullpath=fullpath)\n\n\ndef serve_images(request, *, pk, path):\n    document_root = safe_join(f\"/{settings.IMAGE_FILES_SUBDIRECTORY}\", str(pk))\n    path = posixpath.normpath(path).lstrip(\"/\")\n    name = safe_join(document_root, path)\n\n    try:\n        image = Image.objects.get(pk=pk)\n    except Image.DoesNotExist:\n        raise Http404(\"File not found.\")\n\n    try:\n        user, _ = TokenAuthentication().authenticate(request)\n    except (AuthenticationFailed, TypeError):\n        user = request.user\n\n    if user_can_download_image(user=user, image=image):\n        return protected_storage_redirect(name=name)\n\n    raise Http404(\"File not found.\")\n\n\ndef serve_submissions(request, *, submission_pk, **_):\n    try:\n        submission = Submission.objects.get(pk=submission_pk)\n    except Submission.DoesNotExist:\n        raise Http404(\"File not found.\")\n\n    if user_can_download_submission(user=request.user, submission=submission):\n        return protected_storage_redirect(name=submission.file.name)\n\n    raise Http404(\"File not found.\")\n", "path": "app/grandchallenge/serving/views.py"}]}