We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Cache does not get invalidated correctly when LanguageTreeNode is deleted
### Describe the Bug
<!-- A clear and concise description of what the bug is. -->
If you delete a language the page tree still shows the translation status of the corresponding language. This is probably a caching issue.

Cache does not get invalidated correctly when LanguageTreeNode is deleted
### Describe the Bug
<!-- A clear and concise description of what the bug is. -->
If you delete a language the page tree still shows the translation status of the corresponding language. This is probably a caching issue.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `integreat_cms/cms/views/language_tree/language_tree_actions.py`
Content:
```
1 """
2 This module contains view actions for the language tree.
3 Typically, they do not render a whole page, but only parts of it or they redirect to regular views.
4 """
5 import logging
6 
7 from django.contrib import messages
8 from django.shortcuts import redirect, get_object_or_404
9 from django.utils.translation import ugettext as _
10 from django.views.decorators.http import require_POST
11 from django.db import transaction
12 
13 from treebeard.exceptions import InvalidPosition, InvalidMoveToDescendant
14 
15 from ...constants import position
16 from ...decorators import permission_required
17 from ...models import LanguageTreeNode
18 
19 logger = logging.getLogger(__name__)
20 
21 
22 @require_POST
23 @permission_required("cms.change_languagetreenode")
24 @transaction.atomic
25 def move_language_tree_node(
26     request, region_slug, language_tree_node_id, target_id, target_position
27 ):
28     """
29     This action moves the given language tree node to the given position relative to the given target.
30 
31     :param request: The current request
32     :type request: ~django.http.HttpResponse
33 
34     :param region_slug: The slug of the region which language tree should be modified
35     :type region_slug: str
36 
37     :param language_tree_node_id: The id of the language tree node which should be moved
38     :type language_tree_node_id: int
39 
40     :param target_id: The id of the target language tree node
41     :type target_id: int
42 
43     :param target_position: The desired position (choices: :mod:`~integreat_cms.cms.constants.position`)
44     :type target_position: str
45 
46     :return: A redirection to the language tree
47     :rtype: ~django.http.HttpResponseRedirect
48     """
49 
50     region = request.region
51     language_tree_node = get_object_or_404(
52         region.language_tree_nodes, id=language_tree_node_id
53     )
54     target = get_object_or_404(region.language_tree_nodes, id=target_id)
55 
56     try:
57         if target.depth == 1 and target_position in [position.LEFT, position.RIGHT]:
58             raise InvalidPosition(_("A region can only have one root language."))
59         language_tree_node.move(target, target_position)
60         # Call the save method on the (reloaded) node in order to trigger possible signal handlers etc.
61         # (The move()-method executes raw sql which might cause problems if the instance isn't fetched again)
62         language_tree_node = LanguageTreeNode.objects.get(id=language_tree_node_id)
63         language_tree_node.save()
64         messages.success(
65             request,
66             _('The language tree node "{}" was successfully moved.').format(
67                 language_tree_node.translated_name
68             ),
69         )
70         logger.debug(
71             "%r moved to %r of %r by %r",
72             language_tree_node,
73             target_position,
74             target,
75             request.user,
76         )
77     except (ValueError, InvalidPosition, InvalidMoveToDescendant) as e:
78         messages.error(request, e)
79         logger.exception(e)
80 
81     return redirect("language_tree", **{"region_slug": region_slug})
82 
83 
84 @require_POST
85 @permission_required("cms.delete_languagetreenode")
86 @transaction.atomic
87 def delete_language_tree_node(request, region_slug, language_tree_node_id):
88     """
89     Deletes the language node of distinct region
90     and all page translations for this language
91 
92     :param request: The current request
93     :type request: ~django.http.HttpResponse
94 
95     :param region_slug: The slug of the region which language node should be deleted
96     :type region_slug: str
97 
98     :param language_tree_node_id: The id of the language tree node which should be deleted
99     :type language_tree_node_id: int
100 
101     :return: A redirection to the language tree
102     :rtype: ~django.http.HttpResponseRedirect
103     """
104     # get current region
105     region = request.region
106     # get current selected language node
107     language_node = get_object_or_404(
108         region.language_tree_nodes, id=language_tree_node_id
109     )
110     # get all page translation assigned to the language node
111     page_translations = language_node.language.page_translations
112     # filter those translation that belong to the region and delete them
113     page_translations.filter(page__region=region).delete()
114     # get all event translation assigned to the language node
115     event_translations = language_node.language.event_translations
116     # filter those translation that belong to the region and delete them
117     event_translations.filter(event__region=region).delete()
118     # get all poi translation assigned to the language node
119     poi_translations = language_node.language.poi_translations
120     # filter those translation that belong to the region and delete them
121     poi_translations.filter(poi__region=region).delete()
122     # get all push notification translation assigned to the language node
123     push_notification_translations = (
124         language_node.language.push_notification_translations
125     )
126     # filter those translation that belong to the region and delete them
127     push_notification_translations.filter(push_notification__region=region).delete()
128 
129     logger.debug("%r deleted by %r", language_node, request.user)
130     language_node.delete()
131     messages.success(
132         request,
133         _(
134             'The language tree node "{}" and all corresponding translations were successfully deleted.'
135         ).format(language_node.translated_name),
136     )
137     return redirect("language_tree", **{"region_slug": region_slug})
138
```
--- 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/integreat_cms/cms/views/language_tree/language_tree_actions.py b/integreat_cms/cms/views/language_tree/language_tree_actions.py
--- a/integreat_cms/cms/views/language_tree/language_tree_actions.py
+++ b/integreat_cms/cms/views/language_tree/language_tree_actions.py
@@ -11,6 +11,7 @@
 from django.db import transaction
 
 from treebeard.exceptions import InvalidPosition, InvalidMoveToDescendant
+from cacheops import invalidate_obj
 
 from ...constants import position
 from ...decorators import permission_required
@@ -128,6 +129,16 @@
 
     logger.debug("%r deleted by %r", language_node, request.user)
     language_node.delete()
+
+    for page in region.pages.all():
+        invalidate_obj(page)
+    for event in region.events.all():
+        invalidate_obj(event)
+    for poi in region.pois.all():
+        invalidate_obj(poi)
+    for push_notification in region.push_notifications.all():
+        invalidate_obj(push_notification)
+
     messages.success(
         request,
         _(

{"golden_diff": "diff --git a/integreat_cms/cms/views/language_tree/language_tree_actions.py b/integreat_cms/cms/views/language_tree/language_tree_actions.py\n--- a/integreat_cms/cms/views/language_tree/language_tree_actions.py\n+++ b/integreat_cms/cms/views/language_tree/language_tree_actions.py\n@@ -11,6 +11,7 @@\n from django.db import transaction\n \n from treebeard.exceptions import InvalidPosition, InvalidMoveToDescendant\n+from cacheops import invalidate_obj\n \n from ...constants import position\n from ...decorators import permission_required\n@@ -128,6 +129,16 @@\n \n     logger.debug(\"%r deleted by %r\", language_node, request.user)\n     language_node.delete()\n+\n+    for page in region.pages.all():\n+        invalidate_obj(page)\n+    for event in region.events.all():\n+        invalidate_obj(event)\n+    for poi in region.pois.all():\n+        invalidate_obj(poi)\n+    for push_notification in region.push_notifications.all():\n+        invalidate_obj(push_notification)\n+\n     messages.success(\n         request,\n         _(\n", "issue": "Cache does not get invalidated correctly when LanguageTreeNode is deleted\n### Describe the Bug\r\n<!-- A clear and concise description of what the bug is. -->\r\nIf you delete a language the page tree still shows the translation status of the corresponding language. This is probably a caching issue.\r\n\nCache does not get invalidated correctly when LanguageTreeNode is deleted\n### Describe the Bug\r\n<!-- A clear and concise description of what the bug is. -->\r\nIf you delete a language the page tree still shows the translation status of the corresponding language. This is probably a caching issue.\r\n\n", "before_files": [{"content": "\"\"\"\nThis module contains view actions for the language tree.\nTypically, they do not render a whole page, but only parts of it or they redirect to regular views.\n\"\"\"\nimport logging\n\nfrom django.contrib import messages\nfrom django.shortcuts import redirect, get_object_or_404\nfrom django.utils.translation import ugettext as _\nfrom django.views.decorators.http import require_POST\nfrom django.db import transaction\n\nfrom treebeard.exceptions import InvalidPosition, InvalidMoveToDescendant\n\nfrom ...constants import position\nfrom ...decorators import permission_required\nfrom ...models import LanguageTreeNode\n\nlogger = logging.getLogger(__name__)\n\n\n@require_POST\n@permission_required(\"cms.change_languagetreenode\")\n@transaction.atomic\ndef move_language_tree_node(\n    request, region_slug, language_tree_node_id, target_id, target_position\n):\n    \"\"\"\n    This action moves the given language tree node to the given position relative to the given target.\n\n    :param request: The current request\n    :type request: ~django.http.HttpResponse\n\n    :param region_slug: The slug of the region which language tree should be modified\n    :type region_slug: str\n\n    :param language_tree_node_id: The id of the language tree node which should be moved\n    :type language_tree_node_id: int\n\n    :param target_id: The id of the target language tree node\n    :type target_id: int\n\n    :param target_position: The desired position (choices: :mod:`~integreat_cms.cms.constants.position`)\n    :type target_position: str\n\n    :return: A redirection to the language tree\n    :rtype: ~django.http.HttpResponseRedirect\n    \"\"\"\n\n    region = request.region\n    language_tree_node = get_object_or_404(\n        region.language_tree_nodes, id=language_tree_node_id\n    )\n    target = get_object_or_404(region.language_tree_nodes, id=target_id)\n\n    try:\n        if target.depth == 1 and target_position in [position.LEFT, position.RIGHT]:\n            raise InvalidPosition(_(\"A region can only have one root language.\"))\n        language_tree_node.move(target, target_position)\n        # Call the save method on the (reloaded) node in order to trigger possible signal handlers etc.\n        # (The move()-method executes raw sql which might cause problems if the instance isn't fetched again)\n        language_tree_node = LanguageTreeNode.objects.get(id=language_tree_node_id)\n        language_tree_node.save()\n        messages.success(\n            request,\n            _('The language tree node \"{}\" was successfully moved.').format(\n                language_tree_node.translated_name\n            ),\n        )\n        logger.debug(\n            \"%r moved to %r of %r by %r\",\n            language_tree_node,\n            target_position,\n            target,\n            request.user,\n        )\n    except (ValueError, InvalidPosition, InvalidMoveToDescendant) as e:\n        messages.error(request, e)\n        logger.exception(e)\n\n    return redirect(\"language_tree\", **{\"region_slug\": region_slug})\n\n\n@require_POST\n@permission_required(\"cms.delete_languagetreenode\")\n@transaction.atomic\ndef delete_language_tree_node(request, region_slug, language_tree_node_id):\n    \"\"\"\n    Deletes the language node of distinct region\n    and all page translations for this language\n\n    :param request: The current request\n    :type request: ~django.http.HttpResponse\n\n    :param region_slug: The slug of the region which language node should be deleted\n    :type region_slug: str\n\n    :param language_tree_node_id: The id of the language tree node which should be deleted\n    :type language_tree_node_id: int\n\n    :return: A redirection to the language tree\n    :rtype: ~django.http.HttpResponseRedirect\n    \"\"\"\n    # get current region\n    region = request.region\n    # get current selected language node\n    language_node = get_object_or_404(\n        region.language_tree_nodes, id=language_tree_node_id\n    )\n    # get all page translation assigned to the language node\n    page_translations = language_node.language.page_translations\n    # filter those translation that belong to the region and delete them\n    page_translations.filter(page__region=region).delete()\n    # get all event translation assigned to the language node\n    event_translations = language_node.language.event_translations\n    # filter those translation that belong to the region and delete them\n    event_translations.filter(event__region=region).delete()\n    # get all poi translation assigned to the language node\n    poi_translations = language_node.language.poi_translations\n    # filter those translation that belong to the region and delete them\n    poi_translations.filter(poi__region=region).delete()\n    # get all push notification translation assigned to the language node\n    push_notification_translations = (\n        language_node.language.push_notification_translations\n    )\n    # filter those translation that belong to the region and delete them\n    push_notification_translations.filter(push_notification__region=region).delete()\n\n    logger.debug(\"%r deleted by %r\", language_node, request.user)\n    language_node.delete()\n    messages.success(\n        request,\n        _(\n            'The language tree node \"{}\" and all corresponding translations were successfully deleted.'\n        ).format(language_node.translated_name),\n    )\n    return redirect(\"language_tree\", **{\"region_slug\": region_slug})\n", "path": "integreat_cms/cms/views/language_tree/language_tree_actions.py"}], "after_files": [{"content": "\"\"\"\nThis module contains view actions for the language tree.\nTypically, they do not render a whole page, but only parts of it or they redirect to regular views.\n\"\"\"\nimport logging\n\nfrom django.contrib import messages\nfrom django.shortcuts import redirect, get_object_or_404\nfrom django.utils.translation import ugettext as _\nfrom django.views.decorators.http import require_POST\nfrom django.db import transaction\n\nfrom treebeard.exceptions import InvalidPosition, InvalidMoveToDescendant\nfrom cacheops import invalidate_obj\n\nfrom ...constants import position\nfrom ...decorators import permission_required\nfrom ...models import LanguageTreeNode\n\nlogger = logging.getLogger(__name__)\n\n\n@require_POST\n@permission_required(\"cms.change_languagetreenode\")\n@transaction.atomic\ndef move_language_tree_node(\n    request, region_slug, language_tree_node_id, target_id, target_position\n):\n    \"\"\"\n    This action moves the given language tree node to the given position relative to the given target.\n\n    :param request: The current request\n    :type request: ~django.http.HttpResponse\n\n    :param region_slug: The slug of the region which language tree should be modified\n    :type region_slug: str\n\n    :param language_tree_node_id: The id of the language tree node which should be moved\n    :type language_tree_node_id: int\n\n    :param target_id: The id of the target language tree node\n    :type target_id: int\n\n    :param target_position: The desired position (choices: :mod:`~integreat_cms.cms.constants.position`)\n    :type target_position: str\n\n    :return: A redirection to the language tree\n    :rtype: ~django.http.HttpResponseRedirect\n    \"\"\"\n\n    region = request.region\n    language_tree_node = get_object_or_404(\n        region.language_tree_nodes, id=language_tree_node_id\n    )\n    target = get_object_or_404(region.language_tree_nodes, id=target_id)\n\n    try:\n        if target.depth == 1 and target_position in [position.LEFT, position.RIGHT]:\n            raise InvalidPosition(_(\"A region can only have one root language.\"))\n        language_tree_node.move(target, target_position)\n        # Call the save method on the (reloaded) node in order to trigger possible signal handlers etc.\n        # (The move()-method executes raw sql which might cause problems if the instance isn't fetched again)\n        language_tree_node = LanguageTreeNode.objects.get(id=language_tree_node_id)\n        language_tree_node.save()\n        messages.success(\n            request,\n            _('The language tree node \"{}\" was successfully moved.').format(\n                language_tree_node.translated_name\n            ),\n        )\n        logger.debug(\n            \"%r moved to %r of %r by %r\",\n            language_tree_node,\n            target_position,\n            target,\n            request.user,\n        )\n    except (ValueError, InvalidPosition, InvalidMoveToDescendant) as e:\n        messages.error(request, e)\n        logger.exception(e)\n\n    return redirect(\"language_tree\", **{\"region_slug\": region_slug})\n\n\n@require_POST\n@permission_required(\"cms.delete_languagetreenode\")\n@transaction.atomic\ndef delete_language_tree_node(request, region_slug, language_tree_node_id):\n    \"\"\"\n    Deletes the language node of distinct region\n    and all page translations for this language\n\n    :param request: The current request\n    :type request: ~django.http.HttpResponse\n\n    :param region_slug: The slug of the region which language node should be deleted\n    :type region_slug: str\n\n    :param language_tree_node_id: The id of the language tree node which should be deleted\n    :type language_tree_node_id: int\n\n    :return: A redirection to the language tree\n    :rtype: ~django.http.HttpResponseRedirect\n    \"\"\"\n    # get current region\n    region = request.region\n    # get current selected language node\n    language_node = get_object_or_404(\n        region.language_tree_nodes, id=language_tree_node_id\n    )\n    # get all page translation assigned to the language node\n    page_translations = language_node.language.page_translations\n    # filter those translation that belong to the region and delete them\n    page_translations.filter(page__region=region).delete()\n    # get all event translation assigned to the language node\n    event_translations = language_node.language.event_translations\n    # filter those translation that belong to the region and delete them\n    event_translations.filter(event__region=region).delete()\n    # get all poi translation assigned to the language node\n    poi_translations = language_node.language.poi_translations\n    # filter those translation that belong to the region and delete them\n    poi_translations.filter(poi__region=region).delete()\n    # get all push notification translation assigned to the language node\n    push_notification_translations = (\n        language_node.language.push_notification_translations\n    )\n    # filter those translation that belong to the region and delete them\n    push_notification_translations.filter(push_notification__region=region).delete()\n\n    logger.debug(\"%r deleted by %r\", language_node, request.user)\n    language_node.delete()\n\n    for page in region.pages.all():\n        invalidate_obj(page)\n    for event in region.events.all():\n        invalidate_obj(event)\n    for poi in region.pois.all():\n        invalidate_obj(poi)\n    for push_notification in region.push_notifications.all():\n        invalidate_obj(push_notification)\n\n    messages.success(\n        request,\n        _(\n            'The language tree node \"{}\" and all corresponding translations were successfully deleted.'\n        ).format(language_node.translated_name),\n    )\n    return redirect(\"language_tree\", **{\"region_slug\": region_slug})\n", "path": "integreat_cms/cms/views/language_tree/language_tree_actions.py"}]}