prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Language Tree isn't handled correctly by cache in Page Tree
  ### Describe the Bug
  So far, our Table rows aren't consistent after we delete a language tree node and recreate it. We should probably empty the cacheops cache after we delete a language tree node.
  
  
  </issue>
  <code>
  [start of integreat_cms/cms/forms/language_tree/language_tree_node_form.py]
  1 import logging
  2 
  3 from django import forms
  4 from django.utils.text import capfirst
  5 from django.utils.translation import ugettext_lazy as _
  6 
  7 from ..custom_model_form import CustomModelForm
  8 from ..custom_tree_node_form import CustomTreeNodeForm
  9 from ...models import Language, LanguageTreeNode
  10 
  11 
  12 logger = logging.getLogger(__name__)
  13 
  14 
  15 class LanguageTreeNodeForm(CustomModelForm, CustomTreeNodeForm):
  16     """
  17     Form for creating and modifying language tree node objects
  18     """
  19 
  20     parent = forms.ModelChoiceField(
  21         queryset=LanguageTreeNode.objects.all(),
  22         required=False,
  23         label=capfirst(LanguageTreeNode._meta.get_field("parent").verbose_name),
  24     )
  25 
  26     class Meta:
  27         """
  28         This class contains additional meta configuration of the form class, see the :class:`django.forms.ModelForm`
  29         for more information.
  30         """
  31 
  32         #: The model of this :class:`django.forms.ModelForm`
  33         model = LanguageTreeNode
  34         #: The fields of the model which should be handled by this form
  35         fields = ["language", "visible", "active"]
  36 
  37     def __init__(self, **kwargs):
  38         r"""
  39         Initialize language tree node form
  40 
  41         :param \**kwargs: The supplied keyword arguments
  42         :type \**kwargs: dict
  43         """
  44 
  45         if "data" in kwargs:
  46             # Copy QueryDict because it is immutable
  47             data = kwargs.pop("data").copy()
  48             # Use the parent node as value for the ref node
  49             data["_ref_node_id"] = data["parent"]
  50             data["_position"] = "first-child"
  51             # Set the kwargs to updated POST data again
  52             kwargs["data"] = data
  53 
  54         # Instantiate CustomModelForm
  55         super().__init__(**kwargs)
  56 
  57         parent_queryset = self.instance.region.language_tree_nodes
  58 
  59         if self.instance.id:
  60             descendant_ids = [
  61                 descendant.id
  62                 for descendant in self.instance.get_cached_descendants(
  63                     include_self=True
  64                 )
  65             ]
  66             parent_queryset = parent_queryset.exclude(id__in=descendant_ids)
  67             self.fields["parent"].initial = self.instance.parent_id
  68             excluded_languages = [
  69                 language.id
  70                 for language in self.instance.region.languages
  71                 if language != self.instance.language
  72             ]
  73         else:
  74             excluded_languages = [
  75                 language.id for language in self.instance.region.languages
  76             ]
  77 
  78         # limit possible parents to nodes of current region
  79         self.fields["parent"].queryset = parent_queryset
  80         self.fields["_ref_node_id"].choices = self.fields["parent"].choices
  81         # limit possible languages to those which are not yet included in the tree
  82         self.fields["language"].queryset = Language.objects.exclude(
  83             id__in=excluded_languages
  84         )
  85 
  86     def clean(self):
  87         """
  88         Validate form fields which depend on each other, see :meth:`django.forms.Form.clean`:
  89         Don't allow multiple root nodes for one region:
  90         If self is a root node and the region already has a default language, raise a
  91         :class:`~django.core.exceptions.ValidationError`.
  92 
  93         :return: The cleaned form data
  94         :rtype: dict
  95         """
  96         cleaned_data = super().clean()
  97         default_language = self.instance.region.default_language
  98         # There are two cases in which this error is thrown.
  99         # Both cases include that the parent field is None.
  100         # 1. The instance does exist:
  101         #   - The default language is different from the instance language
  102         # 2. The instance does not exist:
  103         #   - The default language exists
  104         if not cleaned_data.get("parent") and (
  105             (self.instance.id and default_language != self.instance.language)
  106             or (not self.instance.id and default_language)
  107         ):
  108             self.add_error(
  109                 "parent",
  110                 forms.ValidationError(
  111                     _(
  112                         "This region has already a default language."
  113                         "Please specify a source language for this language."
  114                     ),
  115                     code="invalid",
  116                 ),
  117             )
  118         logger.debug(
  119             "LanguageTreeNodeForm validated [2] with cleaned data %r", cleaned_data
  120         )
  121         return cleaned_data
  122
  [end of integreat_cms/cms/forms/language_tree/language_tree_node_form.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/integreat_cms/cms/forms/language_tree/language_tree_node_form.py b/integreat_cms/cms/forms/language_tree/language_tree_node_form.py
  --- a/integreat_cms/cms/forms/language_tree/language_tree_node_form.py
  +++ b/integreat_cms/cms/forms/language_tree/language_tree_node_form.py
  @@ -4,6 +4,8 @@
   from django.utils.text import capfirst
   from django.utils.translation import ugettext_lazy as _
   
  +from cacheops import invalidate_obj
  +
   from ..custom_model_form import CustomModelForm
   from ..custom_tree_node_form import CustomTreeNodeForm
   from ...models import Language, LanguageTreeNode
  @@ -119,3 +121,25 @@
               "LanguageTreeNodeForm validated [2] with cleaned data %r", cleaned_data
           )
           return cleaned_data
  +
  +    def save(self, commit=True):
  +        """
  +        This method extends the default ``save()``-method of the base :class:`~django.forms.ModelForm` to flush
  +        the cache after commiting.
  +
  +        :param commit: Whether or not the changes should be written to the database
  +        :type commit: bool
  +
  +        :return: The saved page translation object
  +        :rtype: ~integreat_cms.cms.models.pages.page_translation.PageTranslation
  +        """
  +        # Save CustomModelForm and flush Cache
  +        result = super().save(commit=commit)
  +
  +        for page in self.instance.region.pages.all():
  +            invalidate_obj(page)
  +        for poi in self.instance.region.pois.all():
  +            invalidate_obj(poi)
  +        for event in self.instance.region.events.all():
  +            invalidate_obj(event)
  +        return result
  
verification_info: {"golden_diff": "diff --git a/integreat_cms/cms/forms/language_tree/language_tree_node_form.py b/integreat_cms/cms/forms/language_tree/language_tree_node_form.py\n--- a/integreat_cms/cms/forms/language_tree/language_tree_node_form.py\n+++ b/integreat_cms/cms/forms/language_tree/language_tree_node_form.py\n@@ -4,6 +4,8 @@\n from django.utils.text import capfirst\n from django.utils.translation import ugettext_lazy as _\n \n+from cacheops import invalidate_obj\n+\n from ..custom_model_form import CustomModelForm\n from ..custom_tree_node_form import CustomTreeNodeForm\n from ...models import Language, LanguageTreeNode\n@@ -119,3 +121,25 @@\n             \"LanguageTreeNodeForm validated [2] with cleaned data %r\", cleaned_data\n         )\n         return cleaned_data\n+\n+    def save(self, commit=True):\n+        \"\"\"\n+        This method extends the default ``save()``-method of the base :class:`~django.forms.ModelForm` to flush\n+        the cache after commiting.\n+\n+        :param commit: Whether or not the changes should be written to the database\n+        :type commit: bool\n+\n+        :return: The saved page translation object\n+        :rtype: ~integreat_cms.cms.models.pages.page_translation.PageTranslation\n+        \"\"\"\n+        # Save CustomModelForm and flush Cache\n+        result = super().save(commit=commit)\n+\n+        for page in self.instance.region.pages.all():\n+            invalidate_obj(page)\n+        for poi in self.instance.region.pois.all():\n+            invalidate_obj(poi)\n+        for event in self.instance.region.events.all():\n+            invalidate_obj(event)\n+        return result\n", "issue": "Language Tree isn't handled correctly by cache in Page Tree\n### Describe the Bug\r\nSo far, our Table rows aren't consistent after we delete a language tree node and recreate it. We should probably empty the cacheops cache after we delete a language tree node.\r\n\n", "before_files": [{"content": "import logging\n\nfrom django import forms\nfrom django.utils.text import capfirst\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom ..custom_model_form import CustomModelForm\nfrom ..custom_tree_node_form import CustomTreeNodeForm\nfrom ...models import Language, LanguageTreeNode\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass LanguageTreeNodeForm(CustomModelForm, CustomTreeNodeForm):\n    \"\"\"\n    Form for creating and modifying language tree node objects\n    \"\"\"\n\n    parent = forms.ModelChoiceField(\n        queryset=LanguageTreeNode.objects.all(),\n        required=False,\n        label=capfirst(LanguageTreeNode._meta.get_field(\"parent\").verbose_name),\n    )\n\n    class Meta:\n        \"\"\"\n        This class contains additional meta configuration of the form class, see the :class:`django.forms.ModelForm`\n        for more information.\n        \"\"\"\n\n        #: The model of this :class:`django.forms.ModelForm`\n        model = LanguageTreeNode\n        #: The fields of the model which should be handled by this form\n        fields = [\"language\", \"visible\", \"active\"]\n\n    def __init__(self, **kwargs):\n        r\"\"\"\n        Initialize language tree node form\n\n        :param \\**kwargs: The supplied keyword arguments\n        :type \\**kwargs: dict\n        \"\"\"\n\n        if \"data\" in kwargs:\n            # Copy QueryDict because it is immutable\n            data = kwargs.pop(\"data\").copy()\n            # Use the parent node as value for the ref node\n            data[\"_ref_node_id\"] = data[\"parent\"]\n            data[\"_position\"] = \"first-child\"\n            # Set the kwargs to updated POST data again\n            kwargs[\"data\"] = data\n\n        # Instantiate CustomModelForm\n        super().__init__(**kwargs)\n\n        parent_queryset = self.instance.region.language_tree_nodes\n\n        if self.instance.id:\n            descendant_ids = [\n                descendant.id\n                for descendant in self.instance.get_cached_descendants(\n                    include_self=True\n                )\n            ]\n            parent_queryset = parent_queryset.exclude(id__in=descendant_ids)\n            self.fields[\"parent\"].initial = self.instance.parent_id\n            excluded_languages = [\n                language.id\n                for language in self.instance.region.languages\n                if language != self.instance.language\n            ]\n        else:\n            excluded_languages = [\n                language.id for language in self.instance.region.languages\n            ]\n\n        # limit possible parents to nodes of current region\n        self.fields[\"parent\"].queryset = parent_queryset\n        self.fields[\"_ref_node_id\"].choices = self.fields[\"parent\"].choices\n        # limit possible languages to those which are not yet included in the tree\n        self.fields[\"language\"].queryset = Language.objects.exclude(\n            id__in=excluded_languages\n        )\n\n    def clean(self):\n        \"\"\"\n        Validate form fields which depend on each other, see :meth:`django.forms.Form.clean`:\n        Don't allow multiple root nodes for one region:\n        If self is a root node and the region already has a default language, raise a\n        :class:`~django.core.exceptions.ValidationError`.\n\n        :return: The cleaned form data\n        :rtype: dict\n        \"\"\"\n        cleaned_data = super().clean()\n        default_language = self.instance.region.default_language\n        # There are two cases in which this error is thrown.\n        # Both cases include that the parent field is None.\n        # 1. The instance does exist:\n        #   - The default language is different from the instance language\n        # 2. The instance does not exist:\n        #   - The default language exists\n        if not cleaned_data.get(\"parent\") and (\n            (self.instance.id and default_language != self.instance.language)\n            or (not self.instance.id and default_language)\n        ):\n            self.add_error(\n                \"parent\",\n                forms.ValidationError(\n                    _(\n                        \"This region has already a default language.\"\n                        \"Please specify a source language for this language.\"\n                    ),\n                    code=\"invalid\",\n                ),\n            )\n        logger.debug(\n            \"LanguageTreeNodeForm validated [2] with cleaned data %r\", cleaned_data\n        )\n        return cleaned_data\n", "path": "integreat_cms/cms/forms/language_tree/language_tree_node_form.py"}]}