We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Crash when trying to delete a region
### Describe the Bug
Deleting a region via this page: 
![grafik](https://user-images.githubusercontent.com/78504586/122641895-558a4280-d108-11eb-93db-2bd36f8b3ce2.png)
fails with a `FieldError`:
![grafik](https://user-images.githubusercontent.com/78504586/122641888-42777280-d108-11eb-9344-86ecfb40b78a.png)


### Steps to Reproduce

1. Go to the regions tab
2. Edit any region
3. Scroll down and click on delete. Click ok on the warning.
4. See the error

### Expected Behavior
The server does not fail and deletes the region


### Actual Behavior
The server crashes and does not delete the region


### Additional Information
/

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/cms/views/regions/region_actions.py`
Content:
```
1 """
2 This module contains view actions for region objects.
3 """
4 import logging
5 
6 from django.contrib import messages
7 from django.contrib.auth import get_user_model
8 from django.contrib.auth.decorators import login_required, permission_required
9 from django.shortcuts import redirect
10 from django.utils.translation import ugettext as _
11 from django.views.decorators.http import require_POST
12 
13 from ...decorators import staff_required
14 from ...models import Region
15 
16 logger = logging.getLogger(__name__)
17 
18 
19 @require_POST
20 @login_required
21 @staff_required
22 @permission_required("cms.manage_regions", raise_exception=True)
23 # pylint: disable=unused-argument
24 def delete_region(request, *args, **kwargs):
25     """
26     This view deletes a region. All content is cascade deleted. Region users, who are not assigned to any other region,
27     are manually removed.
28 
29     :param request: The current request
30     :type request: ~django.http.HttpResponse
31 
32     :param args: The supplied arguments
33     :type args: list
34 
35     :param kwargs: The supplied keyword arguments
36     :type kwargs: dict
37 
38     :raises ~django.core.exceptions.PermissionDenied: If user does not have the permission to manage regions
39 
40     :return: A redirection to the media library
41     :rtype: ~django.http.HttpResponseRedirect
42     """
43 
44     region = Region.get_current_region(request)
45     # Remove hierarchy to prevent ProtectedError when children get deleted before their parents
46     region.pages.update(parent=None)
47     region.language_tree_nodes.update(parent=None)
48     # Delete region and cascade delete all contents
49     deleted_objects = region.delete()
50     logger.info(
51         "%r deleted %r, cascade deleted objects: %r",
52         request.user.profile,
53         region,
54         deleted_objects,
55     )
56     # Get orphan users who aren't superuser or staff and don't have a region assigned
57     # (Creating users with these combination is impossible, so they were region users of the deleted region before)
58     orphan_users = get_user_model().objects.filter(
59         is_superuser=False, is_staff=False, profile__regions=None
60     )
61     if orphan_users.exists():
62         logger.info(
63             "Deleted orphan users: %r",
64             orphan_users,
65         )
66         orphan_users.delete()
67 
68     messages.success(request, _("Region was successfully deleted"))
69 
70     return redirect("regions")
71
```

Path: `src/cms/models/languages/language_tree_node.py`
Content:
```
1 from mptt.fields import TreeForeignKey
2 from mptt.models import MPTTModel, raise_if_unsaved
3 
4 from django.db import models
5 from django.utils import timezone
6 from django.utils.translation import ugettext_lazy as _
7 
8 from .language import Language
9 from ..regions.region import Region
10 
11 
12 class LanguageTreeNode(MPTTModel):
13     """
14     Data model representing a region's language tree. Each tree node is a single object instance and the whole tree is
15     identified by the root node. The base functionality inherits from the package `django-mptt
16     <https://django-mptt.readthedocs.io/en/latest/index.html>`_ (Modified Preorder Tree Traversal).
17     """
18 
19     language = models.ForeignKey(
20         Language,
21         on_delete=models.PROTECT,
22         related_name="language_tree_nodes",
23         verbose_name=_("language"),
24     )
25     parent = TreeForeignKey(
26         "self",
27         blank=True,
28         null=True,
29         on_delete=models.PROTECT,
30         related_name="children",
31         verbose_name=_("source language"),
32     )
33     region = models.ForeignKey(
34         Region,
35         on_delete=models.CASCADE,
36         related_name="language_tree_nodes",
37         verbose_name=_("region"),
38     )
39     visible = models.BooleanField(
40         default=True,
41         verbose_name=_("visible"),
42         help_text=_("Defined if this language should be delivered via the API"),
43     )
44     active = models.BooleanField(
45         default=True,
46         verbose_name=_("active"),
47         help_text=_("Defined if content in this language can be created or edited"),
48     )
49     created_date = models.DateTimeField(
50         default=timezone.now,
51         verbose_name=_("creation date"),
52     )
53     last_updated = models.DateTimeField(
54         auto_now=True,
55         verbose_name=_("modification date"),
56     )
57 
58     @property
59     def slug(self):
60         """
61         Returns the slug of this node's language
62 
63         :return: The language slug of this language node
64         :rtype: str
65         """
66         return self.language.slug
67 
68     @property
69     def native_name(self):
70         """
71         Returns the native name of this node's language
72 
73         :return: The native name of this language node
74         :rtype: str
75         """
76         return self.language.native_name
77 
78     @property
79     def english_name(self):
80         """
81         Returns the name of this node's language in English
82 
83         :return: The English name of this language node
84         :rtype: str
85         """
86         return self.language.english_name
87 
88     @property
89     def translated_name(self):
90         """
91         Returns the name of this node's language in the current backend language
92 
93         :return: The translated name of this language node
94         :rtype: str
95         """
96         return self.language.translated_name
97 
98     @property
99     def text_direction(self):
100         """
101         Returns the text direction (e.g. left-to-right) of this node's language
102 
103         :return: The text direction name of this language node
104         :rtype: str
105         """
106         return self.language.text_direction
107 
108     @property
109     def depth(self):
110         """
111         Counts how many ancestors the node has. If the node is the root node, its depth is `0`.
112 
113         :return: The depth of this language node
114         :rtype: str
115         """
116         return len(self.get_ancestors())
117 
118     # Explicitly define functions to show documentation of base model
119     @raise_if_unsaved
120     def get_ancestors(self, ascending=False, include_self=False):
121         return super().get_ancestors(ascending, include_self)
122 
123     # pylint: disable=useless-super-delegation
124     @raise_if_unsaved
125     def get_family(self):
126         return super().get_family()
127 
128     @raise_if_unsaved
129     def get_children(self):
130         return super().get_children()
131 
132     @raise_if_unsaved
133     def get_descendants(self, include_self=False):
134         return super().get_descendants(include_self)
135 
136     def get_descendant_count(self):
137         return super().get_descendant_count()
138 
139     @raise_if_unsaved
140     def get_root(self):
141         return super().get_root()
142 
143     # pylint: disable=useless-super-delegation
144     def insert_at(
145         self,
146         target,
147         position="first-child",
148         save=False,
149         allow_existing_pk=False,
150         refresh_target=True,
151     ):
152         return super().insert_at(
153             target, position, save, allow_existing_pk, refresh_target
154         )
155 
156     # pylint: disable=useless-super-delegation
157     def move_to(self, target, position="first-child"):
158         return super().move_to(target, position)
159 
160     def __str__(self):
161         """
162         This overwrites the default Django :meth:`~django.db.models.Model.__str__` method which would return ``LanguageTreeNode object (id)``.
163         It is used in the Django admin backend and as label for ModelChoiceFields.
164 
165         :return: A readable string representation of the language node
166         :rtype: str
167         """
168         return self.translated_name
169 
170     def __repr__(self):
171         """
172         This overwrites the default Django ``__repr__()`` method which would return ``<LanguageTreeNode: LanguageTreeNode object (id)>``.
173         It is used for logging.
174 
175         :return: The canonical string representation of the language node
176         :rtype: str
177         """
178         return f"<LanguageTreeNode (id: {self.id}, language: {self.language.slug}, region: {self.region})>"
179 
180     class Meta:
181         #: The verbose name of the model
182         verbose_name = _("language tree node")
183         #: The plural verbose name of the model
184         verbose_name_plural = _("language tree nodes")
185         #: There cannot be two language tree nodes with the same region and language
186         unique_together = (
187             (
188                 "language",
189                 "region",
190             ),
191         )
192         #: The default permissions for this model
193         default_permissions = ()
194         #: The custom permissions for this model
195         permissions = (("manage_language_tree", "Can manage language tree"),)
196         #: The fields which are used to sort the returned objects of a QuerySet
197         ordering = ["region", "level", "parent"]
198
```
--- 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/src/cms/models/languages/language_tree_node.py b/src/cms/models/languages/language_tree_node.py
--- a/src/cms/models/languages/language_tree_node.py
+++ b/src/cms/models/languages/language_tree_node.py
@@ -194,4 +194,4 @@
         #: The custom permissions for this model
         permissions = (("manage_language_tree", "Can manage language tree"),)
         #: The fields which are used to sort the returned objects of a QuerySet
-        ordering = ["region", "level", "parent"]
+        ordering = ["region", "level", "parent__pk"]
diff --git a/src/cms/views/regions/region_actions.py b/src/cms/views/regions/region_actions.py
--- a/src/cms/views/regions/region_actions.py
+++ b/src/cms/views/regions/region_actions.py
@@ -45,6 +45,8 @@
     # Remove hierarchy to prevent ProtectedError when children get deleted before their parents
     region.pages.update(parent=None)
     region.language_tree_nodes.update(parent=None)
+    # Prevent ProtectedError when location gets deleted before their events
+    region.events.update(location=None)
     # Delete region and cascade delete all contents
     deleted_objects = region.delete()
     logger.info(

{"golden_diff": "diff --git a/src/cms/models/languages/language_tree_node.py b/src/cms/models/languages/language_tree_node.py\n--- a/src/cms/models/languages/language_tree_node.py\n+++ b/src/cms/models/languages/language_tree_node.py\n@@ -194,4 +194,4 @@\n         #: The custom permissions for this model\n         permissions = ((\"manage_language_tree\", \"Can manage language tree\"),)\n         #: The fields which are used to sort the returned objects of a QuerySet\n-        ordering = [\"region\", \"level\", \"parent\"]\n+        ordering = [\"region\", \"level\", \"parent__pk\"]\ndiff --git a/src/cms/views/regions/region_actions.py b/src/cms/views/regions/region_actions.py\n--- a/src/cms/views/regions/region_actions.py\n+++ b/src/cms/views/regions/region_actions.py\n@@ -45,6 +45,8 @@\n     # Remove hierarchy to prevent ProtectedError when children get deleted before their parents\n     region.pages.update(parent=None)\n     region.language_tree_nodes.update(parent=None)\n+    # Prevent ProtectedError when location gets deleted before their events\n+    region.events.update(location=None)\n     # Delete region and cascade delete all contents\n     deleted_objects = region.delete()\n     logger.info(\n", "issue": "Crash when trying to delete a region\n### Describe the Bug\r\nDeleting a region via this page: \r\n![grafik](https://user-images.githubusercontent.com/78504586/122641895-558a4280-d108-11eb-93db-2bd36f8b3ce2.png)\r\nfails with a `FieldError`:\r\n![grafik](https://user-images.githubusercontent.com/78504586/122641888-42777280-d108-11eb-9344-86ecfb40b78a.png)\r\n\r\n\r\n### Steps to Reproduce\r\n\r\n1. Go to the regions tab\r\n2. Edit any region\r\n3. Scroll down and click on delete. Click ok on the warning.\r\n4. See the error\r\n\r\n### Expected Behavior\r\nThe server does not fail and deletes the region\r\n\r\n\r\n### Actual Behavior\r\nThe server crashes and does not delete the region\r\n\r\n\r\n### Additional Information\r\n/\n", "before_files": [{"content": "\"\"\"\nThis module contains view actions for region objects.\n\"\"\"\nimport logging\n\nfrom django.contrib import messages\nfrom django.contrib.auth import get_user_model\nfrom django.contrib.auth.decorators import login_required, permission_required\nfrom django.shortcuts import redirect\nfrom django.utils.translation import ugettext as _\nfrom django.views.decorators.http import require_POST\n\nfrom ...decorators import staff_required\nfrom ...models import Region\n\nlogger = logging.getLogger(__name__)\n\n\n@require_POST\n@login_required\n@staff_required\n@permission_required(\"cms.manage_regions\", raise_exception=True)\n# pylint: disable=unused-argument\ndef delete_region(request, *args, **kwargs):\n    \"\"\"\n    This view deletes a region. All content is cascade deleted. Region users, who are not assigned to any other region,\n    are manually removed.\n\n    :param request: The current request\n    :type request: ~django.http.HttpResponse\n\n    :param args: The supplied arguments\n    :type args: list\n\n    :param kwargs: The supplied keyword arguments\n    :type kwargs: dict\n\n    :raises ~django.core.exceptions.PermissionDenied: If user does not have the permission to manage regions\n\n    :return: A redirection to the media library\n    :rtype: ~django.http.HttpResponseRedirect\n    \"\"\"\n\n    region = Region.get_current_region(request)\n    # Remove hierarchy to prevent ProtectedError when children get deleted before their parents\n    region.pages.update(parent=None)\n    region.language_tree_nodes.update(parent=None)\n    # Delete region and cascade delete all contents\n    deleted_objects = region.delete()\n    logger.info(\n        \"%r deleted %r, cascade deleted objects: %r\",\n        request.user.profile,\n        region,\n        deleted_objects,\n    )\n    # Get orphan users who aren't superuser or staff and don't have a region assigned\n    # (Creating users with these combination is impossible, so they were region users of the deleted region before)\n    orphan_users = get_user_model().objects.filter(\n        is_superuser=False, is_staff=False, profile__regions=None\n    )\n    if orphan_users.exists():\n        logger.info(\n            \"Deleted orphan users: %r\",\n            orphan_users,\n        )\n        orphan_users.delete()\n\n    messages.success(request, _(\"Region was successfully deleted\"))\n\n    return redirect(\"regions\")\n", "path": "src/cms/views/regions/region_actions.py"}, {"content": "from mptt.fields import TreeForeignKey\nfrom mptt.models import MPTTModel, raise_if_unsaved\n\nfrom django.db import models\nfrom django.utils import timezone\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom .language import Language\nfrom ..regions.region import Region\n\n\nclass LanguageTreeNode(MPTTModel):\n    \"\"\"\n    Data model representing a region's language tree. Each tree node is a single object instance and the whole tree is\n    identified by the root node. The base functionality inherits from the package `django-mptt\n    <https://django-mptt.readthedocs.io/en/latest/index.html>`_ (Modified Preorder Tree Traversal).\n    \"\"\"\n\n    language = models.ForeignKey(\n        Language,\n        on_delete=models.PROTECT,\n        related_name=\"language_tree_nodes\",\n        verbose_name=_(\"language\"),\n    )\n    parent = TreeForeignKey(\n        \"self\",\n        blank=True,\n        null=True,\n        on_delete=models.PROTECT,\n        related_name=\"children\",\n        verbose_name=_(\"source language\"),\n    )\n    region = models.ForeignKey(\n        Region,\n        on_delete=models.CASCADE,\n        related_name=\"language_tree_nodes\",\n        verbose_name=_(\"region\"),\n    )\n    visible = models.BooleanField(\n        default=True,\n        verbose_name=_(\"visible\"),\n        help_text=_(\"Defined if this language should be delivered via the API\"),\n    )\n    active = models.BooleanField(\n        default=True,\n        verbose_name=_(\"active\"),\n        help_text=_(\"Defined if content in this language can be created or edited\"),\n    )\n    created_date = models.DateTimeField(\n        default=timezone.now,\n        verbose_name=_(\"creation date\"),\n    )\n    last_updated = models.DateTimeField(\n        auto_now=True,\n        verbose_name=_(\"modification date\"),\n    )\n\n    @property\n    def slug(self):\n        \"\"\"\n        Returns the slug of this node's language\n\n        :return: The language slug of this language node\n        :rtype: str\n        \"\"\"\n        return self.language.slug\n\n    @property\n    def native_name(self):\n        \"\"\"\n        Returns the native name of this node's language\n\n        :return: The native name of this language node\n        :rtype: str\n        \"\"\"\n        return self.language.native_name\n\n    @property\n    def english_name(self):\n        \"\"\"\n        Returns the name of this node's language in English\n\n        :return: The English name of this language node\n        :rtype: str\n        \"\"\"\n        return self.language.english_name\n\n    @property\n    def translated_name(self):\n        \"\"\"\n        Returns the name of this node's language in the current backend language\n\n        :return: The translated name of this language node\n        :rtype: str\n        \"\"\"\n        return self.language.translated_name\n\n    @property\n    def text_direction(self):\n        \"\"\"\n        Returns the text direction (e.g. left-to-right) of this node's language\n\n        :return: The text direction name of this language node\n        :rtype: str\n        \"\"\"\n        return self.language.text_direction\n\n    @property\n    def depth(self):\n        \"\"\"\n        Counts how many ancestors the node has. If the node is the root node, its depth is `0`.\n\n        :return: The depth of this language node\n        :rtype: str\n        \"\"\"\n        return len(self.get_ancestors())\n\n    # Explicitly define functions to show documentation of base model\n    @raise_if_unsaved\n    def get_ancestors(self, ascending=False, include_self=False):\n        return super().get_ancestors(ascending, include_self)\n\n    # pylint: disable=useless-super-delegation\n    @raise_if_unsaved\n    def get_family(self):\n        return super().get_family()\n\n    @raise_if_unsaved\n    def get_children(self):\n        return super().get_children()\n\n    @raise_if_unsaved\n    def get_descendants(self, include_self=False):\n        return super().get_descendants(include_self)\n\n    def get_descendant_count(self):\n        return super().get_descendant_count()\n\n    @raise_if_unsaved\n    def get_root(self):\n        return super().get_root()\n\n    # pylint: disable=useless-super-delegation\n    def insert_at(\n        self,\n        target,\n        position=\"first-child\",\n        save=False,\n        allow_existing_pk=False,\n        refresh_target=True,\n    ):\n        return super().insert_at(\n            target, position, save, allow_existing_pk, refresh_target\n        )\n\n    # pylint: disable=useless-super-delegation\n    def move_to(self, target, position=\"first-child\"):\n        return super().move_to(target, position)\n\n    def __str__(self):\n        \"\"\"\n        This overwrites the default Django :meth:`~django.db.models.Model.__str__` method which would return ``LanguageTreeNode object (id)``.\n        It is used in the Django admin backend and as label for ModelChoiceFields.\n\n        :return: A readable string representation of the language node\n        :rtype: str\n        \"\"\"\n        return self.translated_name\n\n    def __repr__(self):\n        \"\"\"\n        This overwrites the default Django ``__repr__()`` method which would return ``<LanguageTreeNode: LanguageTreeNode object (id)>``.\n        It is used for logging.\n\n        :return: The canonical string representation of the language node\n        :rtype: str\n        \"\"\"\n        return f\"<LanguageTreeNode (id: {self.id}, language: {self.language.slug}, region: {self.region})>\"\n\n    class Meta:\n        #: The verbose name of the model\n        verbose_name = _(\"language tree node\")\n        #: The plural verbose name of the model\n        verbose_name_plural = _(\"language tree nodes\")\n        #: There cannot be two language tree nodes with the same region and language\n        unique_together = (\n            (\n                \"language\",\n                \"region\",\n            ),\n        )\n        #: The default permissions for this model\n        default_permissions = ()\n        #: The custom permissions for this model\n        permissions = ((\"manage_language_tree\", \"Can manage language tree\"),)\n        #: The fields which are used to sort the returned objects of a QuerySet\n        ordering = [\"region\", \"level\", \"parent\"]\n", "path": "src/cms/models/languages/language_tree_node.py"}], "after_files": [{"content": "\"\"\"\nThis module contains view actions for region objects.\n\"\"\"\nimport logging\n\nfrom django.contrib import messages\nfrom django.contrib.auth import get_user_model\nfrom django.contrib.auth.decorators import login_required, permission_required\nfrom django.shortcuts import redirect\nfrom django.utils.translation import ugettext as _\nfrom django.views.decorators.http import require_POST\n\nfrom ...decorators import staff_required\nfrom ...models import Region\n\nlogger = logging.getLogger(__name__)\n\n\n@require_POST\n@login_required\n@staff_required\n@permission_required(\"cms.manage_regions\", raise_exception=True)\n# pylint: disable=unused-argument\ndef delete_region(request, *args, **kwargs):\n    \"\"\"\n    This view deletes a region. All content is cascade deleted. Region users, who are not assigned to any other region,\n    are manually removed.\n\n    :param request: The current request\n    :type request: ~django.http.HttpResponse\n\n    :param args: The supplied arguments\n    :type args: list\n\n    :param kwargs: The supplied keyword arguments\n    :type kwargs: dict\n\n    :raises ~django.core.exceptions.PermissionDenied: If user does not have the permission to manage regions\n\n    :return: A redirection to the media library\n    :rtype: ~django.http.HttpResponseRedirect\n    \"\"\"\n\n    region = Region.get_current_region(request)\n    # Remove hierarchy to prevent ProtectedError when children get deleted before their parents\n    region.pages.update(parent=None)\n    region.language_tree_nodes.update(parent=None)\n    # Prevent ProtectedError when location gets deleted before their events\n    region.events.update(location=None)\n    # Delete region and cascade delete all contents\n    deleted_objects = region.delete()\n    logger.info(\n        \"%r deleted %r, cascade deleted objects: %r\",\n        request.user.profile,\n        region,\n        deleted_objects,\n    )\n    # Get orphan users who aren't superuser or staff and don't have a region assigned\n    # (Creating users with these combination is impossible, so they were region users of the deleted region before)\n    orphan_users = get_user_model().objects.filter(\n        is_superuser=False, is_staff=False, profile__regions=None\n    )\n    if orphan_users.exists():\n        logger.info(\n            \"Deleted orphan users: %r\",\n            orphan_users,\n        )\n        orphan_users.delete()\n\n    messages.success(request, _(\"Region was successfully deleted\"))\n\n    return redirect(\"regions\")\n", "path": "src/cms/views/regions/region_actions.py"}, {"content": "from mptt.fields import TreeForeignKey\nfrom mptt.models import MPTTModel, raise_if_unsaved\n\nfrom django.db import models\nfrom django.utils import timezone\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom .language import Language\nfrom ..regions.region import Region\n\n\nclass LanguageTreeNode(MPTTModel):\n    \"\"\"\n    Data model representing a region's language tree. Each tree node is a single object instance and the whole tree is\n    identified by the root node. The base functionality inherits from the package `django-mptt\n    <https://django-mptt.readthedocs.io/en/latest/index.html>`_ (Modified Preorder Tree Traversal).\n    \"\"\"\n\n    language = models.ForeignKey(\n        Language,\n        on_delete=models.PROTECT,\n        related_name=\"language_tree_nodes\",\n        verbose_name=_(\"language\"),\n    )\n    parent = TreeForeignKey(\n        \"self\",\n        blank=True,\n        null=True,\n        on_delete=models.PROTECT,\n        related_name=\"children\",\n        verbose_name=_(\"source language\"),\n    )\n    region = models.ForeignKey(\n        Region,\n        on_delete=models.CASCADE,\n        related_name=\"language_tree_nodes\",\n        verbose_name=_(\"region\"),\n    )\n    visible = models.BooleanField(\n        default=True,\n        verbose_name=_(\"visible\"),\n        help_text=_(\"Defined if this language should be delivered via the API\"),\n    )\n    active = models.BooleanField(\n        default=True,\n        verbose_name=_(\"active\"),\n        help_text=_(\"Defined if content in this language can be created or edited\"),\n    )\n    created_date = models.DateTimeField(\n        default=timezone.now,\n        verbose_name=_(\"creation date\"),\n    )\n    last_updated = models.DateTimeField(\n        auto_now=True,\n        verbose_name=_(\"modification date\"),\n    )\n\n    @property\n    def slug(self):\n        \"\"\"\n        Returns the slug of this node's language\n\n        :return: The language slug of this language node\n        :rtype: str\n        \"\"\"\n        return self.language.slug\n\n    @property\n    def native_name(self):\n        \"\"\"\n        Returns the native name of this node's language\n\n        :return: The native name of this language node\n        :rtype: str\n        \"\"\"\n        return self.language.native_name\n\n    @property\n    def english_name(self):\n        \"\"\"\n        Returns the name of this node's language in English\n\n        :return: The English name of this language node\n        :rtype: str\n        \"\"\"\n        return self.language.english_name\n\n    @property\n    def translated_name(self):\n        \"\"\"\n        Returns the name of this node's language in the current backend language\n\n        :return: The translated name of this language node\n        :rtype: str\n        \"\"\"\n        return self.language.translated_name\n\n    @property\n    def text_direction(self):\n        \"\"\"\n        Returns the text direction (e.g. left-to-right) of this node's language\n\n        :return: The text direction name of this language node\n        :rtype: str\n        \"\"\"\n        return self.language.text_direction\n\n    @property\n    def depth(self):\n        \"\"\"\n        Counts how many ancestors the node has. If the node is the root node, its depth is `0`.\n\n        :return: The depth of this language node\n        :rtype: str\n        \"\"\"\n        return len(self.get_ancestors())\n\n    # Explicitly define functions to show documentation of base model\n    @raise_if_unsaved\n    def get_ancestors(self, ascending=False, include_self=False):\n        return super().get_ancestors(ascending, include_self)\n\n    # pylint: disable=useless-super-delegation\n    @raise_if_unsaved\n    def get_family(self):\n        return super().get_family()\n\n    @raise_if_unsaved\n    def get_children(self):\n        return super().get_children()\n\n    @raise_if_unsaved\n    def get_descendants(self, include_self=False):\n        return super().get_descendants(include_self)\n\n    def get_descendant_count(self):\n        return super().get_descendant_count()\n\n    @raise_if_unsaved\n    def get_root(self):\n        return super().get_root()\n\n    # pylint: disable=useless-super-delegation\n    def insert_at(\n        self,\n        target,\n        position=\"first-child\",\n        save=False,\n        allow_existing_pk=False,\n        refresh_target=True,\n    ):\n        return super().insert_at(\n            target, position, save, allow_existing_pk, refresh_target\n        )\n\n    # pylint: disable=useless-super-delegation\n    def move_to(self, target, position=\"first-child\"):\n        return super().move_to(target, position)\n\n    def __str__(self):\n        \"\"\"\n        This overwrites the default Django :meth:`~django.db.models.Model.__str__` method which would return ``LanguageTreeNode object (id)``.\n        It is used in the Django admin backend and as label for ModelChoiceFields.\n\n        :return: A readable string representation of the language node\n        :rtype: str\n        \"\"\"\n        return self.translated_name\n\n    def __repr__(self):\n        \"\"\"\n        This overwrites the default Django ``__repr__()`` method which would return ``<LanguageTreeNode: LanguageTreeNode object (id)>``.\n        It is used for logging.\n\n        :return: The canonical string representation of the language node\n        :rtype: str\n        \"\"\"\n        return f\"<LanguageTreeNode (id: {self.id}, language: {self.language.slug}, region: {self.region})>\"\n\n    class Meta:\n        #: The verbose name of the model\n        verbose_name = _(\"language tree node\")\n        #: The plural verbose name of the model\n        verbose_name_plural = _(\"language tree nodes\")\n        #: There cannot be two language tree nodes with the same region and language\n        unique_together = (\n            (\n                \"language\",\n                \"region\",\n            ),\n        )\n        #: The default permissions for this model\n        default_permissions = ()\n        #: The custom permissions for this model\n        permissions = ((\"manage_language_tree\", \"Can manage language tree\"),)\n        #: The fields which are used to sort the returned objects of a QuerySet\n        ordering = [\"region\", \"level\", \"parent__pk\"]\n", "path": "src/cms/models/languages/language_tree_node.py"}]}