We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Pragma no cache for path graph json
As in https://github.com/makinacorpus/django-mapentity/pull/48

Related https://github.com/makinacorpus/Geotrek/issues/1026


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `geotrek/core/views.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 import json
3 from django.http import HttpResponse
4 from django.utils.decorators import method_decorator
5 from django.contrib.auth.decorators import login_required
6 from django.views.decorators.http import last_modified as cache_last_modified
7 from django.views.generic.edit import BaseDetailView
8 from django.core.cache import get_cache
9 from django.shortcuts import redirect
10 
11 from mapentity.views import (MapEntityLayer, MapEntityList, MapEntityJsonList,
12                              MapEntityDetail, MapEntityDocument, MapEntityCreate, MapEntityUpdate,
13                              MapEntityDelete, MapEntityFormat,
14                              JSONResponseMixin, HttpJSONResponse, LastModifiedMixin)
15 
16 from geotrek.authent.decorators import path_manager_required, same_structure_required
17 
18 from .models import Path, Trail
19 from .forms import PathForm
20 from .filters import PathFilter
21 from . import graph as graph_lib
22 
23 
24 @login_required
25 def last_list(request):
26     last = request.session.get('last_list')  # set in MapEntityList
27     if not last:
28         return redirect('core:path_list')
29     return redirect(last)
30 
31 home = last_list
32 
33 
34 class HttpSVGResponse(HttpResponse):
35     content_type = 'image/svg+xml'
36     def __init__(self, content='', **kwargs):
37         kwargs['content_type'] = self.content_type
38         super(HttpSVGResponse, self).__init__(content, **kwargs)
39 
40 
41 class ElevationChart(LastModifiedMixin, BaseDetailView):
42 
43     @method_decorator(login_required)
44     def dispatch(self, *args, **kwargs):
45         return super(ElevationChart, self).dispatch(*args, **kwargs)
46 
47     def render_to_response(self, context, **response_kwargs):
48         return HttpSVGResponse(self.get_object().get_elevation_profile_svg(),
49                                **response_kwargs)
50 
51 
52 class ElevationProfile(LastModifiedMixin, JSONResponseMixin, BaseDetailView):
53     """Extract elevation profile from a path and return it as JSON"""
54 
55     @method_decorator(login_required)
56     def dispatch(self, *args, **kwargs):
57         return super(ElevationProfile, self).dispatch(*args, **kwargs)
58 
59     def get_context_data(self, **kwargs):
60         """
61         Put elevation profile into response context.
62         """
63         obj = self.get_object()
64         data = {}
65         # Formatted as distance, elevation, [lng, lat]
66         for step in obj.get_elevation_profile():
67             formatted = step[0], step[3], step[1:3]
68             data.setdefault('profile', []).append(formatted)
69         return data
70 
71 
72 class ElevationArea(LastModifiedMixin, JSONResponseMixin, BaseDetailView):
73     """Extract elevation profile on an area and return it as JSON"""
74 
75     @method_decorator(login_required)
76     def dispatch(self, *args, **kwargs):
77         return super(ElevationArea, self).dispatch(*args, **kwargs)
78 
79     def get_context_data(self, **kwargs):
80         obj = self.get_object()
81         return obj.get_elevation_area()
82 
83 
84 class PathLayer(MapEntityLayer):
85     model = Path
86     properties = ['name']
87 
88 
89 class PathList(MapEntityList):
90     queryset = Path.objects.prefetch_related('networks').select_related('stake', 'trail')
91     filterform = PathFilter
92     columns = ['id', 'name', 'networks', 'stake', 'trail']
93 
94 
95 class PathJsonList(MapEntityJsonList, PathList):
96     pass
97 
98 
99 class PathFormatList(MapEntityFormat, PathList):
100     pass
101 
102 
103 class PathDetail(MapEntityDetail):
104     model = Path
105 
106     def can_edit(self):
107         return self.request.user.is_superuser or \
108                (hasattr(self.request.user, 'profile') and \
109                 self.request.user.profile.is_path_manager and \
110                 self.get_object().same_structure(self.request.user))
111 
112 
113 class PathDocument(MapEntityDocument):
114     model = Path
115 
116     def get_context_data(self, *args, **kwargs):
117         self.get_object().prepare_elevation_chart(self.request)
118         return super(PathDocument, self).get_context_data(*args, **kwargs)
119 
120 
121 class PathCreate(MapEntityCreate):
122     model = Path
123     form_class = PathForm
124 
125     @method_decorator(path_manager_required('core:path_list'))
126     def dispatch(self, *args, **kwargs):
127         return super(PathCreate, self).dispatch(*args, **kwargs)
128 
129 
130 class PathUpdate(MapEntityUpdate):
131     model = Path
132     form_class = PathForm
133 
134     @method_decorator(path_manager_required('core:path_detail'))
135     @same_structure_required('core:path_detail')
136     def dispatch(self, *args, **kwargs):
137         return super(PathUpdate, self).dispatch(*args, **kwargs)
138 
139 
140 class PathDelete(MapEntityDelete):
141     model = Path
142 
143     @method_decorator(path_manager_required('core:path_detail'))
144     @same_structure_required('core:path_detail')
145     def dispatch(self, *args, **kwargs):
146         return super(PathDelete, self).dispatch(*args, **kwargs)
147 
148 
149 @login_required
150 @cache_last_modified(lambda x: Path.latest_updated())
151 def get_graph_json(request):
152     cache = get_cache('fat')
153     key = 'path_graph_json'
154 
155     result = cache.get(key)
156     latest = Path.latest_updated()
157 
158     if result and latest:
159         cache_latest, json_graph = result
160         # Not empty and still valid
161         if cache_latest and cache_latest >= latest:
162             return HttpJSONResponse(json_graph)
163 
164     # cache does not exist or is not up to date
165     # rebuild the graph and cache the json
166     graph = graph_lib.graph_edges_nodes_of_qs(Path.objects.all())
167     json_graph = json.dumps(graph)
168 
169     cache.set(key, (latest, json_graph))
170     return HttpJSONResponse(json_graph)
171 
172 
173 class TrailDetail(MapEntityDetail):
174     model = Trail
175 
176     def can_edit(self):
177         return False
178 
179 
180 class TrailDocument(MapEntityDocument):
181     model = Trail
182
```
--- 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/geotrek/core/views.py b/geotrek/core/views.py
--- a/geotrek/core/views.py
+++ b/geotrek/core/views.py
@@ -4,6 +4,7 @@
 from django.utils.decorators import method_decorator
 from django.contrib.auth.decorators import login_required
 from django.views.decorators.http import last_modified as cache_last_modified
+from django.views.decorators.cache import never_cache as force_cache_validation
 from django.views.generic.edit import BaseDetailView
 from django.core.cache import get_cache
 from django.shortcuts import redirect
@@ -148,6 +149,7 @@
 
 @login_required
 @cache_last_modified(lambda x: Path.latest_updated())
+@force_cache_validation
 def get_graph_json(request):
     cache = get_cache('fat')
     key = 'path_graph_json'

{"golden_diff": "diff --git a/geotrek/core/views.py b/geotrek/core/views.py\n--- a/geotrek/core/views.py\n+++ b/geotrek/core/views.py\n@@ -4,6 +4,7 @@\n from django.utils.decorators import method_decorator\n from django.contrib.auth.decorators import login_required\n from django.views.decorators.http import last_modified as cache_last_modified\n+from django.views.decorators.cache import never_cache as force_cache_validation\n from django.views.generic.edit import BaseDetailView\n from django.core.cache import get_cache\n from django.shortcuts import redirect\n@@ -148,6 +149,7 @@\n \n @login_required\n @cache_last_modified(lambda x: Path.latest_updated())\n+@force_cache_validation\n def get_graph_json(request):\n     cache = get_cache('fat')\n     key = 'path_graph_json'\n", "issue": "Pragma no cache for path graph json\nAs in https://github.com/makinacorpus/django-mapentity/pull/48\n\nRelated https://github.com/makinacorpus/Geotrek/issues/1026\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nimport json\nfrom django.http import HttpResponse\nfrom django.utils.decorators import method_decorator\nfrom django.contrib.auth.decorators import login_required\nfrom django.views.decorators.http import last_modified as cache_last_modified\nfrom django.views.generic.edit import BaseDetailView\nfrom django.core.cache import get_cache\nfrom django.shortcuts import redirect\n\nfrom mapentity.views import (MapEntityLayer, MapEntityList, MapEntityJsonList,\n                             MapEntityDetail, MapEntityDocument, MapEntityCreate, MapEntityUpdate,\n                             MapEntityDelete, MapEntityFormat,\n                             JSONResponseMixin, HttpJSONResponse, LastModifiedMixin)\n\nfrom geotrek.authent.decorators import path_manager_required, same_structure_required\n\nfrom .models import Path, Trail\nfrom .forms import PathForm\nfrom .filters import PathFilter\nfrom . import graph as graph_lib\n\n\n@login_required\ndef last_list(request):\n    last = request.session.get('last_list')  # set in MapEntityList\n    if not last:\n        return redirect('core:path_list')\n    return redirect(last)\n\nhome = last_list\n\n\nclass HttpSVGResponse(HttpResponse):\n    content_type = 'image/svg+xml'\n    def __init__(self, content='', **kwargs):\n        kwargs['content_type'] = self.content_type\n        super(HttpSVGResponse, self).__init__(content, **kwargs)\n\n\nclass ElevationChart(LastModifiedMixin, BaseDetailView):\n\n    @method_decorator(login_required)\n    def dispatch(self, *args, **kwargs):\n        return super(ElevationChart, self).dispatch(*args, **kwargs)\n\n    def render_to_response(self, context, **response_kwargs):\n        return HttpSVGResponse(self.get_object().get_elevation_profile_svg(),\n                               **response_kwargs)\n\n\nclass ElevationProfile(LastModifiedMixin, JSONResponseMixin, BaseDetailView):\n    \"\"\"Extract elevation profile from a path and return it as JSON\"\"\"\n\n    @method_decorator(login_required)\n    def dispatch(self, *args, **kwargs):\n        return super(ElevationProfile, self).dispatch(*args, **kwargs)\n\n    def get_context_data(self, **kwargs):\n        \"\"\"\n        Put elevation profile into response context.\n        \"\"\"\n        obj = self.get_object()\n        data = {}\n        # Formatted as distance, elevation, [lng, lat]\n        for step in obj.get_elevation_profile():\n            formatted = step[0], step[3], step[1:3]\n            data.setdefault('profile', []).append(formatted)\n        return data\n\n\nclass ElevationArea(LastModifiedMixin, JSONResponseMixin, BaseDetailView):\n    \"\"\"Extract elevation profile on an area and return it as JSON\"\"\"\n\n    @method_decorator(login_required)\n    def dispatch(self, *args, **kwargs):\n        return super(ElevationArea, self).dispatch(*args, **kwargs)\n\n    def get_context_data(self, **kwargs):\n        obj = self.get_object()\n        return obj.get_elevation_area()\n\n\nclass PathLayer(MapEntityLayer):\n    model = Path\n    properties = ['name']\n\n\nclass PathList(MapEntityList):\n    queryset = Path.objects.prefetch_related('networks').select_related('stake', 'trail')\n    filterform = PathFilter\n    columns = ['id', 'name', 'networks', 'stake', 'trail']\n\n\nclass PathJsonList(MapEntityJsonList, PathList):\n    pass\n\n\nclass PathFormatList(MapEntityFormat, PathList):\n    pass\n\n\nclass PathDetail(MapEntityDetail):\n    model = Path\n\n    def can_edit(self):\n        return self.request.user.is_superuser or \\\n               (hasattr(self.request.user, 'profile') and \\\n                self.request.user.profile.is_path_manager and \\\n                self.get_object().same_structure(self.request.user))\n\n\nclass PathDocument(MapEntityDocument):\n    model = Path\n\n    def get_context_data(self, *args, **kwargs):\n        self.get_object().prepare_elevation_chart(self.request)\n        return super(PathDocument, self).get_context_data(*args, **kwargs)\n\n\nclass PathCreate(MapEntityCreate):\n    model = Path\n    form_class = PathForm\n\n    @method_decorator(path_manager_required('core:path_list'))\n    def dispatch(self, *args, **kwargs):\n        return super(PathCreate, self).dispatch(*args, **kwargs)\n\n\nclass PathUpdate(MapEntityUpdate):\n    model = Path\n    form_class = PathForm\n\n    @method_decorator(path_manager_required('core:path_detail'))\n    @same_structure_required('core:path_detail')\n    def dispatch(self, *args, **kwargs):\n        return super(PathUpdate, self).dispatch(*args, **kwargs)\n\n\nclass PathDelete(MapEntityDelete):\n    model = Path\n\n    @method_decorator(path_manager_required('core:path_detail'))\n    @same_structure_required('core:path_detail')\n    def dispatch(self, *args, **kwargs):\n        return super(PathDelete, self).dispatch(*args, **kwargs)\n\n\n@login_required\n@cache_last_modified(lambda x: Path.latest_updated())\ndef get_graph_json(request):\n    cache = get_cache('fat')\n    key = 'path_graph_json'\n\n    result = cache.get(key)\n    latest = Path.latest_updated()\n\n    if result and latest:\n        cache_latest, json_graph = result\n        # Not empty and still valid\n        if cache_latest and cache_latest >= latest:\n            return HttpJSONResponse(json_graph)\n\n    # cache does not exist or is not up to date\n    # rebuild the graph and cache the json\n    graph = graph_lib.graph_edges_nodes_of_qs(Path.objects.all())\n    json_graph = json.dumps(graph)\n\n    cache.set(key, (latest, json_graph))\n    return HttpJSONResponse(json_graph)\n\n\nclass TrailDetail(MapEntityDetail):\n    model = Trail\n\n    def can_edit(self):\n        return False\n\n\nclass TrailDocument(MapEntityDocument):\n    model = Trail\n", "path": "geotrek/core/views.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\nimport json\nfrom django.http import HttpResponse\nfrom django.utils.decorators import method_decorator\nfrom django.contrib.auth.decorators import login_required\nfrom django.views.decorators.http import last_modified as cache_last_modified\nfrom django.views.decorators.cache import never_cache as force_cache_validation\nfrom django.views.generic.edit import BaseDetailView\nfrom django.core.cache import get_cache\nfrom django.shortcuts import redirect\n\nfrom mapentity.views import (MapEntityLayer, MapEntityList, MapEntityJsonList,\n                             MapEntityDetail, MapEntityDocument, MapEntityCreate, MapEntityUpdate,\n                             MapEntityDelete, MapEntityFormat,\n                             JSONResponseMixin, HttpJSONResponse, LastModifiedMixin)\n\nfrom geotrek.authent.decorators import path_manager_required, same_structure_required\n\nfrom .models import Path, Trail\nfrom .forms import PathForm\nfrom .filters import PathFilter\nfrom . import graph as graph_lib\n\n\n@login_required\ndef last_list(request):\n    last = request.session.get('last_list')  # set in MapEntityList\n    if not last:\n        return redirect('core:path_list')\n    return redirect(last)\n\nhome = last_list\n\n\nclass HttpSVGResponse(HttpResponse):\n    content_type = 'image/svg+xml'\n    def __init__(self, content='', **kwargs):\n        kwargs['content_type'] = self.content_type\n        super(HttpSVGResponse, self).__init__(content, **kwargs)\n\n\nclass ElevationChart(LastModifiedMixin, BaseDetailView):\n\n    @method_decorator(login_required)\n    def dispatch(self, *args, **kwargs):\n        return super(ElevationChart, self).dispatch(*args, **kwargs)\n\n    def render_to_response(self, context, **response_kwargs):\n        return HttpSVGResponse(self.get_object().get_elevation_profile_svg(),\n                               **response_kwargs)\n\n\nclass ElevationProfile(LastModifiedMixin, JSONResponseMixin, BaseDetailView):\n    \"\"\"Extract elevation profile from a path and return it as JSON\"\"\"\n\n    @method_decorator(login_required)\n    def dispatch(self, *args, **kwargs):\n        return super(ElevationProfile, self).dispatch(*args, **kwargs)\n\n    def get_context_data(self, **kwargs):\n        \"\"\"\n        Put elevation profile into response context.\n        \"\"\"\n        obj = self.get_object()\n        data = {}\n        # Formatted as distance, elevation, [lng, lat]\n        for step in obj.get_elevation_profile():\n            formatted = step[0], step[3], step[1:3]\n            data.setdefault('profile', []).append(formatted)\n        return data\n\n\nclass ElevationArea(LastModifiedMixin, JSONResponseMixin, BaseDetailView):\n    \"\"\"Extract elevation profile on an area and return it as JSON\"\"\"\n\n    @method_decorator(login_required)\n    def dispatch(self, *args, **kwargs):\n        return super(ElevationArea, self).dispatch(*args, **kwargs)\n\n    def get_context_data(self, **kwargs):\n        obj = self.get_object()\n        return obj.get_elevation_area()\n\n\nclass PathLayer(MapEntityLayer):\n    model = Path\n    properties = ['name']\n\n\nclass PathList(MapEntityList):\n    queryset = Path.objects.prefetch_related('networks').select_related('stake', 'trail')\n    filterform = PathFilter\n    columns = ['id', 'name', 'networks', 'stake', 'trail']\n\n\nclass PathJsonList(MapEntityJsonList, PathList):\n    pass\n\n\nclass PathFormatList(MapEntityFormat, PathList):\n    pass\n\n\nclass PathDetail(MapEntityDetail):\n    model = Path\n\n    def can_edit(self):\n        return self.request.user.is_superuser or \\\n               (hasattr(self.request.user, 'profile') and \\\n                self.request.user.profile.is_path_manager and \\\n                self.get_object().same_structure(self.request.user))\n\n\nclass PathDocument(MapEntityDocument):\n    model = Path\n\n    def get_context_data(self, *args, **kwargs):\n        self.get_object().prepare_elevation_chart(self.request)\n        return super(PathDocument, self).get_context_data(*args, **kwargs)\n\n\nclass PathCreate(MapEntityCreate):\n    model = Path\n    form_class = PathForm\n\n    @method_decorator(path_manager_required('core:path_list'))\n    def dispatch(self, *args, **kwargs):\n        return super(PathCreate, self).dispatch(*args, **kwargs)\n\n\nclass PathUpdate(MapEntityUpdate):\n    model = Path\n    form_class = PathForm\n\n    @method_decorator(path_manager_required('core:path_detail'))\n    @same_structure_required('core:path_detail')\n    def dispatch(self, *args, **kwargs):\n        return super(PathUpdate, self).dispatch(*args, **kwargs)\n\n\nclass PathDelete(MapEntityDelete):\n    model = Path\n\n    @method_decorator(path_manager_required('core:path_detail'))\n    @same_structure_required('core:path_detail')\n    def dispatch(self, *args, **kwargs):\n        return super(PathDelete, self).dispatch(*args, **kwargs)\n\n\n@login_required\n@cache_last_modified(lambda x: Path.latest_updated())\n@force_cache_validation\ndef get_graph_json(request):\n    cache = get_cache('fat')\n    key = 'path_graph_json'\n\n    result = cache.get(key)\n    latest = Path.latest_updated()\n\n    if result and latest:\n        cache_latest, json_graph = result\n        # Not empty and still valid\n        if cache_latest and cache_latest >= latest:\n            return HttpJSONResponse(json_graph)\n\n    # cache does not exist or is not up to date\n    # rebuild the graph and cache the json\n    graph = graph_lib.graph_edges_nodes_of_qs(Path.objects.all())\n    json_graph = json.dumps(graph)\n\n    cache.set(key, (latest, json_graph))\n    return HttpJSONResponse(json_graph)\n\n\nclass TrailDetail(MapEntityDetail):\n    model = Trail\n\n    def can_edit(self):\n        return False\n\n\nclass TrailDocument(MapEntityDocument):\n    model = Trail\n", "path": "geotrek/core/views.py"}]}