prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Landscape creation and update
  <!--
  Use a concise title that describes the request.
  Bad: localization
  Good: Translate site into Spanish
  
  Bad: customize hostname
  Good: Determine hostname at build time from environment
  -->
  
  ## Description
  - Default landscape group should be created when a new landscape is created
  - Manager should be assigned at the creation of a landscape
  - Only managers can update landscape data
  
  </issue>
  <code>
  [start of terraso_backend/apps/core/models/landscapes.py]
  1 import structlog
  2 from django.db import models
  3 
  4 from apps.core import permission_rules as perm_rules
  5 
  6 from .commons import BaseModel, SlugModel
  7 from .groups import Group
  8 from .users import User
  9 
  10 logger = structlog.get_logger(__name__)
  11 
  12 
  13 class Landscape(SlugModel):
  14     """
  15     This model represents a Landscape on Terraso platform.
  16 
  17     A Landscape is a socio-ecological system that consists of natural
  18     and/or human-modified ecosystems. Defined by its stakeholds, a
  19     Landscape usually has geographical boundaries. It may correspond to,
  20     or be a combination of, natural boundaries, distinct land features,
  21     socially defined areas such as indigenous territories, and/or
  22     jurisdictional and administrative boundaries. The boundaries of a
  23     Landscape can cross several countries.
  24     """
  25 
  26     name = models.CharField(max_length=128, unique=True)
  27     description = models.TextField(max_length=512, blank=True, default="")
  28     website = models.URLField(blank=True, default="")
  29     location = models.CharField(max_length=128, blank=True, default="")
  30     area_polygon = models.JSONField(blank=True, null=True)
  31 
  32     created_by = models.ForeignKey(
  33         User,
  34         blank=True,
  35         null=True,
  36         on_delete=models.PROTECT,
  37         related_name="created_landscapes",
  38     )
  39     groups = models.ManyToManyField(Group, through="LandscapeGroup")
  40 
  41     field_to_slug = "name"
  42 
  43     class Meta(SlugModel.Meta):
  44         rules_permissions = {
  45             "change": perm_rules.allowed_to_change_landscape,
  46             "delete": perm_rules.allowed_to_delete_landscape,
  47         }
  48 
  49     def get_default_group(self):
  50         """
  51         A default Group in a Landscape is that Group where any
  52         individual (associated or not with other Groups) is added when
  53         associating directly with a Landscape.
  54         """
  55         try:
  56             # associated_groups is the related_name defined on
  57             # LandscapeGroup relationship with Landscape. It returns a
  58             # queryset of LandscapeGroup
  59             landscape_group = self.associated_groups.get(is_default_landscape_group=True)
  60         except LandscapeGroup.DoesNotExist:
  61             logger.error(
  62                 "Landscape has no default group, but it must have", extra={"landscape_id": self.pk}
  63             )
  64             return None
  65 
  66         return landscape_group.group
  67 
  68     def __str__(self):
  69         return self.name
  70 
  71 
  72 class LandscapeGroup(BaseModel):
  73     """
  74     This model represents the association between a Landscape and a Group on
  75     Terraso platform.
  76     """
  77 
  78     landscape = models.ForeignKey(
  79         Landscape, on_delete=models.CASCADE, related_name="associated_groups"
  80     )
  81     group = models.ForeignKey(Group, on_delete=models.CASCADE, related_name="associated_landscapes")
  82 
  83     is_default_landscape_group = models.BooleanField(blank=True, default=False)
  84 
  85     class Meta:
  86         rules_permissions = {
  87             "add": perm_rules.allowed_to_add_landscape_group,
  88             "delete": perm_rules.allowed_to_delete_landscape_group,
  89         }
  90         constraints = (
  91             models.UniqueConstraint(
  92                 fields=("group", "landscape"),
  93                 condition=models.Q(deleted_at__isnull=True),
  94                 name="unique_active_landscape_group",
  95             ),
  96         )
  97
  [end of terraso_backend/apps/core/models/landscapes.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/terraso_backend/apps/core/models/landscapes.py b/terraso_backend/apps/core/models/landscapes.py
  --- a/terraso_backend/apps/core/models/landscapes.py
  +++ b/terraso_backend/apps/core/models/landscapes.py
  @@ -1,5 +1,5 @@
   import structlog
  -from django.db import models
  +from django.db import models, transaction
   
   from apps.core import permission_rules as perm_rules
   
  @@ -46,6 +46,24 @@
               "delete": perm_rules.allowed_to_delete_landscape,
           }
   
  +    def save(self, *args, **kwargs):
  +        with transaction.atomic():
  +            creating = not Landscape.objects.filter(pk=self.pk).exists()
  +
  +            super().save(*args, **kwargs)
  +
  +            if creating and self.created_by:
  +                group = Group(
  +                    name="Group {}".format(self.slug),
  +                    description="",
  +                    created_by=self.created_by,
  +                )
  +                group.save()
  +                landscape_group = LandscapeGroup(
  +                    group=group, landscape=self, is_default_landscape_group=True
  +                )
  +                landscape_group.save()
  +
       def get_default_group(self):
           """
           A default Group in a Landscape is that Group where any
  
verification_info: {"golden_diff": "diff --git a/terraso_backend/apps/core/models/landscapes.py b/terraso_backend/apps/core/models/landscapes.py\n--- a/terraso_backend/apps/core/models/landscapes.py\n+++ b/terraso_backend/apps/core/models/landscapes.py\n@@ -1,5 +1,5 @@\n import structlog\n-from django.db import models\n+from django.db import models, transaction\n \n from apps.core import permission_rules as perm_rules\n \n@@ -46,6 +46,24 @@\n             \"delete\": perm_rules.allowed_to_delete_landscape,\n         }\n \n+    def save(self, *args, **kwargs):\n+        with transaction.atomic():\n+            creating = not Landscape.objects.filter(pk=self.pk).exists()\n+\n+            super().save(*args, **kwargs)\n+\n+            if creating and self.created_by:\n+                group = Group(\n+                    name=\"Group {}\".format(self.slug),\n+                    description=\"\",\n+                    created_by=self.created_by,\n+                )\n+                group.save()\n+                landscape_group = LandscapeGroup(\n+                    group=group, landscape=self, is_default_landscape_group=True\n+                )\n+                landscape_group.save()\n+\n     def get_default_group(self):\n         \"\"\"\n         A default Group in a Landscape is that Group where any\n", "issue": "Landscape creation and update\n<!--\r\nUse a concise title that describes the request.\r\nBad: localization\r\nGood: Translate site into Spanish\r\n\r\nBad: customize hostname\r\nGood: Determine hostname at build time from environment\r\n-->\r\n\r\n## Description\r\n- Default landscape group should be created when a new landscape is created\r\n- Manager should be assigned at the creation of a landscape\r\n- Only managers can update landscape data\n", "before_files": [{"content": "import structlog\nfrom django.db import models\n\nfrom apps.core import permission_rules as perm_rules\n\nfrom .commons import BaseModel, SlugModel\nfrom .groups import Group\nfrom .users import User\n\nlogger = structlog.get_logger(__name__)\n\n\nclass Landscape(SlugModel):\n    \"\"\"\n    This model represents a Landscape on Terraso platform.\n\n    A Landscape is a socio-ecological system that consists of natural\n    and/or human-modified ecosystems. Defined by its stakeholds, a\n    Landscape usually has geographical boundaries. It may correspond to,\n    or be a combination of, natural boundaries, distinct land features,\n    socially defined areas such as indigenous territories, and/or\n    jurisdictional and administrative boundaries. The boundaries of a\n    Landscape can cross several countries.\n    \"\"\"\n\n    name = models.CharField(max_length=128, unique=True)\n    description = models.TextField(max_length=512, blank=True, default=\"\")\n    website = models.URLField(blank=True, default=\"\")\n    location = models.CharField(max_length=128, blank=True, default=\"\")\n    area_polygon = models.JSONField(blank=True, null=True)\n\n    created_by = models.ForeignKey(\n        User,\n        blank=True,\n        null=True,\n        on_delete=models.PROTECT,\n        related_name=\"created_landscapes\",\n    )\n    groups = models.ManyToManyField(Group, through=\"LandscapeGroup\")\n\n    field_to_slug = \"name\"\n\n    class Meta(SlugModel.Meta):\n        rules_permissions = {\n            \"change\": perm_rules.allowed_to_change_landscape,\n            \"delete\": perm_rules.allowed_to_delete_landscape,\n        }\n\n    def get_default_group(self):\n        \"\"\"\n        A default Group in a Landscape is that Group where any\n        individual (associated or not with other Groups) is added when\n        associating directly with a Landscape.\n        \"\"\"\n        try:\n            # associated_groups is the related_name defined on\n            # LandscapeGroup relationship with Landscape. It returns a\n            # queryset of LandscapeGroup\n            landscape_group = self.associated_groups.get(is_default_landscape_group=True)\n        except LandscapeGroup.DoesNotExist:\n            logger.error(\n                \"Landscape has no default group, but it must have\", extra={\"landscape_id\": self.pk}\n            )\n            return None\n\n        return landscape_group.group\n\n    def __str__(self):\n        return self.name\n\n\nclass LandscapeGroup(BaseModel):\n    \"\"\"\n    This model represents the association between a Landscape and a Group on\n    Terraso platform.\n    \"\"\"\n\n    landscape = models.ForeignKey(\n        Landscape, on_delete=models.CASCADE, related_name=\"associated_groups\"\n    )\n    group = models.ForeignKey(Group, on_delete=models.CASCADE, related_name=\"associated_landscapes\")\n\n    is_default_landscape_group = models.BooleanField(blank=True, default=False)\n\n    class Meta:\n        rules_permissions = {\n            \"add\": perm_rules.allowed_to_add_landscape_group,\n            \"delete\": perm_rules.allowed_to_delete_landscape_group,\n        }\n        constraints = (\n            models.UniqueConstraint(\n                fields=(\"group\", \"landscape\"),\n                condition=models.Q(deleted_at__isnull=True),\n                name=\"unique_active_landscape_group\",\n            ),\n        )\n", "path": "terraso_backend/apps/core/models/landscapes.py"}]}