We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Membership edit fails due to form errors
The error is due to missing `comment` field in `MembershipForm`.

`MembershipForm.save()` should be placed in `MembershipCreateForm`, because that's where `comment` field is and that's what should trigger the signal.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `amy/fiscal/forms.py`
Content:
```
1 from django import forms
2 from django.core.validators import RegexValidator
3 from django.dispatch import receiver
4 from markdownx.fields import MarkdownxFormField
5 
6 from workshops.forms import (
7     BootstrapHelper,
8     WidgetOverrideMixin,
9     form_saved_add_comment,
10 )
11 from workshops.models import (
12     Organization,
13     Membership,
14     Sponsorship,
15 )
16 # this is used instead of Django Autocomplete Light widgets
17 # see issue #1330: https://github.com/swcarpentry/amy/issues/1330
18 from workshops.fields import (
19     ModelSelect2,
20 )
21 from workshops.signals import create_comment_signal
22 
23 
24 # settings for Select2
25 # this makes it possible for autocomplete widget to fit in low-width sidebar
26 SIDEBAR_DAL_WIDTH = {
27     'data-width': '100%',
28     'width': 'style',
29 }
30 
31 
32 class OrganizationForm(forms.ModelForm):
33     domain = forms.CharField(
34         max_length=Organization._meta.get_field('domain').max_length,
35         validators=[
36             RegexValidator(
37                 r'[^\w\.-]+', inverse_match=True,
38                 message='Please enter only the domain (such as "math.esu.edu")'
39                         ' without a leading "http://" or a trailing "/".')
40         ],
41     )
42 
43     helper = BootstrapHelper(add_cancel_button=False,
44                              duplicate_buttons_on_top=True)
45 
46     class Meta:
47         model = Organization
48         fields = ['domain', 'fullname', 'country']
49 
50 
51 class OrganizationCreateForm(OrganizationForm):
52     comment = MarkdownxFormField(
53         label='Comment',
54         help_text='This will be added to comments after the organization '
55                   'is created.',
56         widget=forms.Textarea,
57         required=False,
58     )
59 
60     class Meta(OrganizationForm.Meta):
61         fields = OrganizationForm.Meta.fields.copy()
62         fields.append('comment')
63 
64     def save(self, *args, **kwargs):
65         res = super().save(*args, **kwargs)
66 
67         create_comment_signal.send(sender=self.__class__,
68                                    content_object=res,
69                                    comment=self.cleaned_data['comment'],
70                                    timestamp=None)
71 
72         return res
73 
74 
75 class MembershipForm(forms.ModelForm):
76     helper = BootstrapHelper(add_cancel_button=False)
77 
78     organization = forms.ModelChoiceField(
79         label='Organization',
80         required=True,
81         queryset=Organization.objects.all(),
82         widget=ModelSelect2(url='organization-lookup')
83     )
84 
85     class Meta:
86         model = Membership
87         fields = [
88             'organization', 'variant', 'agreement_start', 'agreement_end',
89             'contribution_type', 'workshops_without_admin_fee_per_agreement',
90             'self_organized_workshops_per_agreement',
91             'seats_instructor_training',
92             'additional_instructor_training_seats',
93         ]
94 
95     def save(self, *args, **kwargs):
96         res = super().save(*args, **kwargs)
97 
98         create_comment_signal.send(sender=self.__class__,
99                                    content_object=res,
100                                    comment=self.cleaned_data['comment'],
101                                    timestamp=None)
102 
103         return res
104 
105 
106 class MembershipCreateForm(MembershipForm):
107     comment = MarkdownxFormField(
108         label='Comment',
109         help_text='This will be added to comments after the membership is '
110                   'created.',
111         widget=forms.Textarea,
112         required=False,
113     )
114 
115     class Meta(MembershipForm.Meta):
116         fields = MembershipForm.Meta.fields.copy()
117         fields.append('comment')
118 
119 
120 class SponsorshipForm(WidgetOverrideMixin, forms.ModelForm):
121 
122     helper = BootstrapHelper(submit_label='Add')
123 
124     class Meta:
125         model = Sponsorship
126         fields = '__all__'
127         widgets = {
128             'organization': ModelSelect2(url='organization-lookup'),
129             'event': ModelSelect2(url='event-lookup'),
130             'contact': ModelSelect2(url='person-lookup'),
131         }
132 
133 
134 # ----------------------------------------------------------
135 # Signals
136 
137 # adding @receiver decorator to the function defined in `workshops.forms`
138 form_saved_add_comment = receiver(
139     create_comment_signal,
140     sender=OrganizationCreateForm,
141 )(form_saved_add_comment)
142 
143 # adding @receiver decorator to the function defined in `workshops.forms`
144 form_saved_add_comment = receiver(
145     create_comment_signal,
146     sender=MembershipCreateForm,
147 )(form_saved_add_comment)
148
```
--- 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/amy/fiscal/forms.py b/amy/fiscal/forms.py
--- a/amy/fiscal/forms.py
+++ b/amy/fiscal/forms.py
@@ -92,16 +92,6 @@
             'additional_instructor_training_seats',
         ]
 
-    def save(self, *args, **kwargs):
-        res = super().save(*args, **kwargs)
-
-        create_comment_signal.send(sender=self.__class__,
-                                   content_object=res,
-                                   comment=self.cleaned_data['comment'],
-                                   timestamp=None)
-
-        return res
-
 
 class MembershipCreateForm(MembershipForm):
     comment = MarkdownxFormField(
@@ -116,6 +106,16 @@
         fields = MembershipForm.Meta.fields.copy()
         fields.append('comment')
 
+    def save(self, *args, **kwargs):
+        res = super().save(*args, **kwargs)
+
+        create_comment_signal.send(sender=self.__class__,
+                                   content_object=res,
+                                   comment=self.cleaned_data['comment'],
+                                   timestamp=None)
+
+        return res
+
 
 class SponsorshipForm(WidgetOverrideMixin, forms.ModelForm):

{"golden_diff": "diff --git a/amy/fiscal/forms.py b/amy/fiscal/forms.py\n--- a/amy/fiscal/forms.py\n+++ b/amy/fiscal/forms.py\n@@ -92,16 +92,6 @@\n             'additional_instructor_training_seats',\n         ]\n \n-    def save(self, *args, **kwargs):\n-        res = super().save(*args, **kwargs)\n-\n-        create_comment_signal.send(sender=self.__class__,\n-                                   content_object=res,\n-                                   comment=self.cleaned_data['comment'],\n-                                   timestamp=None)\n-\n-        return res\n-\n \n class MembershipCreateForm(MembershipForm):\n     comment = MarkdownxFormField(\n@@ -116,6 +106,16 @@\n         fields = MembershipForm.Meta.fields.copy()\n         fields.append('comment')\n \n+    def save(self, *args, **kwargs):\n+        res = super().save(*args, **kwargs)\n+\n+        create_comment_signal.send(sender=self.__class__,\n+                                   content_object=res,\n+                                   comment=self.cleaned_data['comment'],\n+                                   timestamp=None)\n+\n+        return res\n+\n \n class SponsorshipForm(WidgetOverrideMixin, forms.ModelForm):\n", "issue": "Membership edit fails due to form errors\nThe error is due to missing `comment` field in `MembershipForm`.\r\n\r\n`MembershipForm.save()` should be placed in `MembershipCreateForm`, because that's where `comment` field is and that's what should trigger the signal.\n", "before_files": [{"content": "from django import forms\nfrom django.core.validators import RegexValidator\nfrom django.dispatch import receiver\nfrom markdownx.fields import MarkdownxFormField\n\nfrom workshops.forms import (\n    BootstrapHelper,\n    WidgetOverrideMixin,\n    form_saved_add_comment,\n)\nfrom workshops.models import (\n    Organization,\n    Membership,\n    Sponsorship,\n)\n# this is used instead of Django Autocomplete Light widgets\n# see issue #1330: https://github.com/swcarpentry/amy/issues/1330\nfrom workshops.fields import (\n    ModelSelect2,\n)\nfrom workshops.signals import create_comment_signal\n\n\n# settings for Select2\n# this makes it possible for autocomplete widget to fit in low-width sidebar\nSIDEBAR_DAL_WIDTH = {\n    'data-width': '100%',\n    'width': 'style',\n}\n\n\nclass OrganizationForm(forms.ModelForm):\n    domain = forms.CharField(\n        max_length=Organization._meta.get_field('domain').max_length,\n        validators=[\n            RegexValidator(\n                r'[^\\w\\.-]+', inverse_match=True,\n                message='Please enter only the domain (such as \"math.esu.edu\")'\n                        ' without a leading \"http://\" or a trailing \"/\".')\n        ],\n    )\n\n    helper = BootstrapHelper(add_cancel_button=False,\n                             duplicate_buttons_on_top=True)\n\n    class Meta:\n        model = Organization\n        fields = ['domain', 'fullname', 'country']\n\n\nclass OrganizationCreateForm(OrganizationForm):\n    comment = MarkdownxFormField(\n        label='Comment',\n        help_text='This will be added to comments after the organization '\n                  'is created.',\n        widget=forms.Textarea,\n        required=False,\n    )\n\n    class Meta(OrganizationForm.Meta):\n        fields = OrganizationForm.Meta.fields.copy()\n        fields.append('comment')\n\n    def save(self, *args, **kwargs):\n        res = super().save(*args, **kwargs)\n\n        create_comment_signal.send(sender=self.__class__,\n                                   content_object=res,\n                                   comment=self.cleaned_data['comment'],\n                                   timestamp=None)\n\n        return res\n\n\nclass MembershipForm(forms.ModelForm):\n    helper = BootstrapHelper(add_cancel_button=False)\n\n    organization = forms.ModelChoiceField(\n        label='Organization',\n        required=True,\n        queryset=Organization.objects.all(),\n        widget=ModelSelect2(url='organization-lookup')\n    )\n\n    class Meta:\n        model = Membership\n        fields = [\n            'organization', 'variant', 'agreement_start', 'agreement_end',\n            'contribution_type', 'workshops_without_admin_fee_per_agreement',\n            'self_organized_workshops_per_agreement',\n            'seats_instructor_training',\n            'additional_instructor_training_seats',\n        ]\n\n    def save(self, *args, **kwargs):\n        res = super().save(*args, **kwargs)\n\n        create_comment_signal.send(sender=self.__class__,\n                                   content_object=res,\n                                   comment=self.cleaned_data['comment'],\n                                   timestamp=None)\n\n        return res\n\n\nclass MembershipCreateForm(MembershipForm):\n    comment = MarkdownxFormField(\n        label='Comment',\n        help_text='This will be added to comments after the membership is '\n                  'created.',\n        widget=forms.Textarea,\n        required=False,\n    )\n\n    class Meta(MembershipForm.Meta):\n        fields = MembershipForm.Meta.fields.copy()\n        fields.append('comment')\n\n\nclass SponsorshipForm(WidgetOverrideMixin, forms.ModelForm):\n\n    helper = BootstrapHelper(submit_label='Add')\n\n    class Meta:\n        model = Sponsorship\n        fields = '__all__'\n        widgets = {\n            'organization': ModelSelect2(url='organization-lookup'),\n            'event': ModelSelect2(url='event-lookup'),\n            'contact': ModelSelect2(url='person-lookup'),\n        }\n\n\n# ----------------------------------------------------------\n# Signals\n\n# adding @receiver decorator to the function defined in `workshops.forms`\nform_saved_add_comment = receiver(\n    create_comment_signal,\n    sender=OrganizationCreateForm,\n)(form_saved_add_comment)\n\n# adding @receiver decorator to the function defined in `workshops.forms`\nform_saved_add_comment = receiver(\n    create_comment_signal,\n    sender=MembershipCreateForm,\n)(form_saved_add_comment)\n", "path": "amy/fiscal/forms.py"}], "after_files": [{"content": "from django import forms\nfrom django.core.validators import RegexValidator\nfrom django.dispatch import receiver\nfrom markdownx.fields import MarkdownxFormField\n\nfrom workshops.forms import (\n    BootstrapHelper,\n    WidgetOverrideMixin,\n    form_saved_add_comment,\n)\nfrom workshops.models import (\n    Organization,\n    Membership,\n    Sponsorship,\n)\n# this is used instead of Django Autocomplete Light widgets\n# see issue #1330: https://github.com/swcarpentry/amy/issues/1330\nfrom workshops.fields import (\n    ModelSelect2,\n)\nfrom workshops.signals import create_comment_signal\n\n\n# settings for Select2\n# this makes it possible for autocomplete widget to fit in low-width sidebar\nSIDEBAR_DAL_WIDTH = {\n    'data-width': '100%',\n    'width': 'style',\n}\n\n\nclass OrganizationForm(forms.ModelForm):\n    domain = forms.CharField(\n        max_length=Organization._meta.get_field('domain').max_length,\n        validators=[\n            RegexValidator(\n                r'[^\\w\\.-]+', inverse_match=True,\n                message='Please enter only the domain (such as \"math.esu.edu\")'\n                        ' without a leading \"http://\" or a trailing \"/\".')\n        ],\n    )\n\n    helper = BootstrapHelper(add_cancel_button=False,\n                             duplicate_buttons_on_top=True)\n\n    class Meta:\n        model = Organization\n        fields = ['domain', 'fullname', 'country']\n\n\nclass OrganizationCreateForm(OrganizationForm):\n    comment = MarkdownxFormField(\n        label='Comment',\n        help_text='This will be added to comments after the organization '\n                  'is created.',\n        widget=forms.Textarea,\n        required=False,\n    )\n\n    class Meta(OrganizationForm.Meta):\n        fields = OrganizationForm.Meta.fields.copy()\n        fields.append('comment')\n\n    def save(self, *args, **kwargs):\n        res = super().save(*args, **kwargs)\n\n        create_comment_signal.send(sender=self.__class__,\n                                   content_object=res,\n                                   comment=self.cleaned_data['comment'],\n                                   timestamp=None)\n\n        return res\n\n\nclass MembershipForm(forms.ModelForm):\n    helper = BootstrapHelper(add_cancel_button=False)\n\n    organization = forms.ModelChoiceField(\n        label='Organization',\n        required=True,\n        queryset=Organization.objects.all(),\n        widget=ModelSelect2(url='organization-lookup')\n    )\n\n    class Meta:\n        model = Membership\n        fields = [\n            'organization', 'variant', 'agreement_start', 'agreement_end',\n            'contribution_type', 'workshops_without_admin_fee_per_agreement',\n            'self_organized_workshops_per_agreement',\n            'seats_instructor_training',\n            'additional_instructor_training_seats',\n        ]\n\n\nclass MembershipCreateForm(MembershipForm):\n    comment = MarkdownxFormField(\n        label='Comment',\n        help_text='This will be added to comments after the membership is '\n                  'created.',\n        widget=forms.Textarea,\n        required=False,\n    )\n\n    class Meta(MembershipForm.Meta):\n        fields = MembershipForm.Meta.fields.copy()\n        fields.append('comment')\n\n    def save(self, *args, **kwargs):\n        res = super().save(*args, **kwargs)\n\n        create_comment_signal.send(sender=self.__class__,\n                                   content_object=res,\n                                   comment=self.cleaned_data['comment'],\n                                   timestamp=None)\n\n        return res\n\n\nclass SponsorshipForm(WidgetOverrideMixin, forms.ModelForm):\n\n    helper = BootstrapHelper(submit_label='Add')\n\n    class Meta:\n        model = Sponsorship\n        fields = '__all__'\n        widgets = {\n            'organization': ModelSelect2(url='organization-lookup'),\n            'event': ModelSelect2(url='event-lookup'),\n            'contact': ModelSelect2(url='person-lookup'),\n        }\n\n\n# ----------------------------------------------------------\n# Signals\n\n# adding @receiver decorator to the function defined in `workshops.forms`\nform_saved_add_comment = receiver(\n    create_comment_signal,\n    sender=OrganizationCreateForm,\n)(form_saved_add_comment)\n\n# adding @receiver decorator to the function defined in `workshops.forms`\nform_saved_add_comment = receiver(\n    create_comment_signal,\n    sender=MembershipCreateForm,\n)(form_saved_add_comment)\n", "path": "amy/fiscal/forms.py"}]}