prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  В админке во всех названиях курса выводить название потока
  Сейчас совершенно непонятно, к какому потоку принадлежит курс — приходится догадываться по старшинству. Надо, чтобы вот тут (см. ниже) выводилось название ProductGroup, к которому привязан курс.
  
  <img width="1511" alt="Screenshot 2022-06-20 at 10 55 18" src="https://user-images.githubusercontent.com/1592663/174552950-bf6ee7e8-6ba7-43f7-af90-5ba2fededfd7.png">
  
  
  
  --- 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/products/models/course.py`
  Content:
  ```
  1 from django.apps import apps
  2 from django.core.exceptions import ValidationError
  3 from django.db.models import OuterRef
  4 from django.db.models import QuerySet
  5 from django.db.models import Subquery
  6 from django.utils.translation import gettext_lazy as _
  7 
  8 from app.files import RandomFileName
  9 from app.models import models
  10 from mailing.tasks import send_mail
  11 from products.models.base import Shippable
  12 from users.models import User
  13 
  14 
  15 class CourseQuerySet(QuerySet):
  16     def for_lms(self) -> QuerySet["Course"]:
  17         return self.filter(
  18             display_in_lms=True,
  19         ).with_course_homepage()
  20 
  21     def with_course_homepage(self) -> QuerySet["Course"]:
  22         materials = (
  23             apps.get_model("notion.Material")
  24             .objects.filter(
  25                 course=OuterRef("pk"),
  26                 is_home_page=True,
  27             )
  28             .order_by(
  29                 "-created",
  30             )
  31             .values(
  32                 "page_id",
  33             )
  34         )
  35 
  36         return self.annotate(
  37             home_page_slug=Subquery(materials[:1]),
  38         )
  39 
  40 
  41 CourseManager = models.Manager.from_queryset(CourseQuerySet)
  42 
  43 
  44 class Course(Shippable):
  45     objects = CourseManager()
  46 
  47     name_genitive = models.CharField(_("Genitive name"), max_length=255, help_text="«мастер-класса о TDD». К примеру для записей.")
  48     zoomus_webinar_id = models.CharField(
  49         _("Zoom.us webinar ID"), max_length=255, null=True, blank=True, help_text=_("If set, every user who purcashes this course gets invited")
  50     )
  51 
  52     welcome_letter_template_id = models.CharField(
  53         _("Welcome letter template id"), max_length=255, blank=True, null=True, help_text=_("Will be sent upon purchase if set")
  54     )
  55     gift_welcome_letter_template_id = models.CharField(
  56         _("Special welcome letter template id for gifts"), max_length=255, blank=True, null=True, help_text=_("If not set, common welcome letter will be used")
  57     )
  58     display_in_lms = models.BooleanField(_("Display in LMS"), default=True, help_text=_("If disabled will not be shown in LMS"))
  59 
  60     diploma_template_context = models.JSONField(default=dict, blank=True)
  61 
  62     disable_triggers = models.BooleanField(_("Disable all triggers"), default=False)
  63 
  64     confirmation_template_id = models.CharField(
  65         _("Confirmation template id"),
  66         max_length=255,
  67         null=True,
  68         blank=True,
  69         help_text=_("If set user sill receive this message upon creating zero-priced order"),
  70     )
  71     confirmation_success_url = models.URLField(_("Confirmation success URL"), null=True, blank=True)
  72 
  73     cover = models.ImageField(
  74         verbose_name=_("Cover image"),
  75         upload_to=RandomFileName("courses/covers"),
  76         blank=True,
  77         help_text=_("The cover image of course"),
  78     )
  79 
  80     class Meta:
  81         ordering = ["-id"]
  82         verbose_name = _("Course")
  83         verbose_name_plural = _("Courses")
  84         db_table = "courses_course"
  85 
  86     def clean(self):
  87         """Check for correct setting of confirmation_template_id and confirmation_success_url"""
  88         if not self.confirmation_template_id and not self.confirmation_success_url:
  89             return
  90 
  91         if not all([self.confirmation_template_id, self.confirmation_success_url]):
  92             raise ValidationError(_("Both confirmation_template_id and confirmation_success_url must be set"))
  93 
  94         if self.price != 0:
  95             raise ValidationError(_("Courses with confirmation should have zero price"))
  96 
  97     def get_purchased_users(self) -> QuerySet[User]:
  98         return User.objects.filter(
  99             pk__in=apps.get_model("studying.Study").objects.filter(course=self).values_list("student", flat=True),
  100         )
  101 
  102     def send_email_to_all_purchased_users(self, template_id: str):
  103         for user in self.get_purchased_users().iterator():
  104             send_mail.delay(
  105                 to=user.email,
  106                 template_id=template_id,
  107             )
  108
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/src/products/models/course.py b/src/products/models/course.py
  --- a/src/products/models/course.py
  +++ b/src/products/models/course.py
  @@ -105,3 +105,11 @@
                   to=user.email,
                   template_id=template_id,
               )
  +
  +    def __str__(self) -> str:
  +        name = getattr(self, "name", None)
  +        group = getattr(self, "group", None)
  +        if name is not None and group is not None:
  +            return f"{name} - {group.name}"
  +
  +        return super().__str__()
  
verification_info: {"golden_diff": "diff --git a/src/products/models/course.py b/src/products/models/course.py\n--- a/src/products/models/course.py\n+++ b/src/products/models/course.py\n@@ -105,3 +105,11 @@\n                 to=user.email,\n                 template_id=template_id,\n             )\n+\n+    def __str__(self) -> str:\n+        name = getattr(self, \"name\", None)\n+        group = getattr(self, \"group\", None)\n+        if name is not None and group is not None:\n+            return f\"{name} - {group.name}\"\n+\n+        return super().__str__()\n", "issue": "\u0412 \u0430\u0434\u043c\u0438\u043d\u043a\u0435 \u0432\u043e \u0432\u0441\u0435\u0445 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f\u0445 \u043a\u0443\u0440\u0441\u0430 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u0430\n\u0421\u0435\u0439\u0447\u0430\u0441 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043a \u043a\u0430\u043a\u043e\u043c\u0443 \u043f\u043e\u0442\u043e\u043a\u0443 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438\u0442 \u043a\u0443\u0440\u0441 \u2014\u00a0\u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u043e\u0433\u0430\u0434\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u0441\u0442\u0430\u0440\u0448\u0438\u043d\u0441\u0442\u0432\u0443. \u041d\u0430\u0434\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u043e\u0442 \u0442\u0443\u0442 (\u0441\u043c. \u043d\u0438\u0436\u0435) \u0432\u044b\u0432\u043e\u0434\u0438\u043b\u043e\u0441\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 ProductGroup, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u043a\u0443\u0440\u0441.\r\n\r\n<img width=\"1511\" alt=\"Screenshot 2022-06-20 at 10 55 18\" src=\"https://user-images.githubusercontent.com/1592663/174552950-bf6ee7e8-6ba7-43f7-af90-5ba2fededfd7.png\">\r\n\r\n\n", "before_files": [{"content": "from django.apps import apps\nfrom django.core.exceptions import ValidationError\nfrom django.db.models import OuterRef\nfrom django.db.models import QuerySet\nfrom django.db.models import Subquery\nfrom django.utils.translation import gettext_lazy as _\n\nfrom app.files import RandomFileName\nfrom app.models import models\nfrom mailing.tasks import send_mail\nfrom products.models.base import Shippable\nfrom users.models import User\n\n\nclass CourseQuerySet(QuerySet):\n    def for_lms(self) -> QuerySet[\"Course\"]:\n        return self.filter(\n            display_in_lms=True,\n        ).with_course_homepage()\n\n    def with_course_homepage(self) -> QuerySet[\"Course\"]:\n        materials = (\n            apps.get_model(\"notion.Material\")\n            .objects.filter(\n                course=OuterRef(\"pk\"),\n                is_home_page=True,\n            )\n            .order_by(\n                \"-created\",\n            )\n            .values(\n                \"page_id\",\n            )\n        )\n\n        return self.annotate(\n            home_page_slug=Subquery(materials[:1]),\n        )\n\n\nCourseManager = models.Manager.from_queryset(CourseQuerySet)\n\n\nclass Course(Shippable):\n    objects = CourseManager()\n\n    name_genitive = models.CharField(_(\"Genitive name\"), max_length=255, help_text=\"\u00ab\u043c\u0430\u0441\u0442\u0435\u0440-\u043a\u043b\u0430\u0441\u0441\u0430 \u043e TDD\u00bb. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0435\u0439.\")\n    zoomus_webinar_id = models.CharField(\n        _(\"Zoom.us webinar ID\"), max_length=255, null=True, blank=True, help_text=_(\"If set, every user who purcashes this course gets invited\")\n    )\n\n    welcome_letter_template_id = models.CharField(\n        _(\"Welcome letter template id\"), max_length=255, blank=True, null=True, help_text=_(\"Will be sent upon purchase if set\")\n    )\n    gift_welcome_letter_template_id = models.CharField(\n        _(\"Special welcome letter template id for gifts\"), max_length=255, blank=True, null=True, help_text=_(\"If not set, common welcome letter will be used\")\n    )\n    display_in_lms = models.BooleanField(_(\"Display in LMS\"), default=True, help_text=_(\"If disabled will not be shown in LMS\"))\n\n    diploma_template_context = models.JSONField(default=dict, blank=True)\n\n    disable_triggers = models.BooleanField(_(\"Disable all triggers\"), default=False)\n\n    confirmation_template_id = models.CharField(\n        _(\"Confirmation template id\"),\n        max_length=255,\n        null=True,\n        blank=True,\n        help_text=_(\"If set user sill receive this message upon creating zero-priced order\"),\n    )\n    confirmation_success_url = models.URLField(_(\"Confirmation success URL\"), null=True, blank=True)\n\n    cover = models.ImageField(\n        verbose_name=_(\"Cover image\"),\n        upload_to=RandomFileName(\"courses/covers\"),\n        blank=True,\n        help_text=_(\"The cover image of course\"),\n    )\n\n    class Meta:\n        ordering = [\"-id\"]\n        verbose_name = _(\"Course\")\n        verbose_name_plural = _(\"Courses\")\n        db_table = \"courses_course\"\n\n    def clean(self):\n        \"\"\"Check for correct setting of confirmation_template_id and confirmation_success_url\"\"\"\n        if not self.confirmation_template_id and not self.confirmation_success_url:\n            return\n\n        if not all([self.confirmation_template_id, self.confirmation_success_url]):\n            raise ValidationError(_(\"Both confirmation_template_id and confirmation_success_url must be set\"))\n\n        if self.price != 0:\n            raise ValidationError(_(\"Courses with confirmation should have zero price\"))\n\n    def get_purchased_users(self) -> QuerySet[User]:\n        return User.objects.filter(\n            pk__in=apps.get_model(\"studying.Study\").objects.filter(course=self).values_list(\"student\", flat=True),\n        )\n\n    def send_email_to_all_purchased_users(self, template_id: str):\n        for user in self.get_purchased_users().iterator():\n            send_mail.delay(\n                to=user.email,\n                template_id=template_id,\n            )\n", "path": "src/products/models/course.py"}], "after_files": [{"content": "from django.apps import apps\nfrom django.core.exceptions import ValidationError\nfrom django.db.models import OuterRef\nfrom django.db.models import QuerySet\nfrom django.db.models import Subquery\nfrom django.utils.translation import gettext_lazy as _\n\nfrom app.files import RandomFileName\nfrom app.models import models\nfrom mailing.tasks import send_mail\nfrom products.models.base import Shippable\nfrom users.models import User\n\n\nclass CourseQuerySet(QuerySet):\n    def for_lms(self) -> QuerySet[\"Course\"]:\n        return self.filter(\n            display_in_lms=True,\n        ).with_course_homepage()\n\n    def with_course_homepage(self) -> QuerySet[\"Course\"]:\n        materials = (\n            apps.get_model(\"notion.Material\")\n            .objects.filter(\n                course=OuterRef(\"pk\"),\n                is_home_page=True,\n            )\n            .order_by(\n                \"-created\",\n            )\n            .values(\n                \"page_id\",\n            )\n        )\n\n        return self.annotate(\n            home_page_slug=Subquery(materials[:1]),\n        )\n\n\nCourseManager = models.Manager.from_queryset(CourseQuerySet)\n\n\nclass Course(Shippable):\n    objects = CourseManager()\n\n    name_genitive = models.CharField(_(\"Genitive name\"), max_length=255, help_text=\"\u00ab\u043c\u0430\u0441\u0442\u0435\u0440-\u043a\u043b\u0430\u0441\u0441\u0430 \u043e TDD\u00bb. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0435\u0439.\")\n    zoomus_webinar_id = models.CharField(\n        _(\"Zoom.us webinar ID\"), max_length=255, null=True, blank=True, help_text=_(\"If set, every user who purcashes this course gets invited\")\n    )\n\n    welcome_letter_template_id = models.CharField(\n        _(\"Welcome letter template id\"), max_length=255, blank=True, null=True, help_text=_(\"Will be sent upon purchase if set\")\n    )\n    gift_welcome_letter_template_id = models.CharField(\n        _(\"Special welcome letter template id for gifts\"), max_length=255, blank=True, null=True, help_text=_(\"If not set, common welcome letter will be used\")\n    )\n    display_in_lms = models.BooleanField(_(\"Display in LMS\"), default=True, help_text=_(\"If disabled will not be shown in LMS\"))\n\n    diploma_template_context = models.JSONField(default=dict, blank=True)\n\n    disable_triggers = models.BooleanField(_(\"Disable all triggers\"), default=False)\n\n    confirmation_template_id = models.CharField(\n        _(\"Confirmation template id\"),\n        max_length=255,\n        null=True,\n        blank=True,\n        help_text=_(\"If set user sill receive this message upon creating zero-priced order\"),\n    )\n    confirmation_success_url = models.URLField(_(\"Confirmation success URL\"), null=True, blank=True)\n\n    cover = models.ImageField(\n        verbose_name=_(\"Cover image\"),\n        upload_to=RandomFileName(\"courses/covers\"),\n        blank=True,\n        help_text=_(\"The cover image of course\"),\n    )\n\n    class Meta:\n        ordering = [\"-id\"]\n        verbose_name = _(\"Course\")\n        verbose_name_plural = _(\"Courses\")\n        db_table = \"courses_course\"\n\n    def clean(self):\n        \"\"\"Check for correct setting of confirmation_template_id and confirmation_success_url\"\"\"\n        if not self.confirmation_template_id and not self.confirmation_success_url:\n            return\n\n        if not all([self.confirmation_template_id, self.confirmation_success_url]):\n            raise ValidationError(_(\"Both confirmation_template_id and confirmation_success_url must be set\"))\n\n        if self.price != 0:\n            raise ValidationError(_(\"Courses with confirmation should have zero price\"))\n\n    def get_purchased_users(self) -> QuerySet[User]:\n        return User.objects.filter(\n            pk__in=apps.get_model(\"studying.Study\").objects.filter(course=self).values_list(\"student\", flat=True),\n        )\n\n    def send_email_to_all_purchased_users(self, template_id: str):\n        for user in self.get_purchased_users().iterator():\n            send_mail.delay(\n                to=user.email,\n                template_id=template_id,\n            )\n\n    def __str__(self) -> str:\n        name = getattr(self, \"name\", None)\n        group = getattr(self, \"group\", None)\n        if name is not None and group is not None:\n            return f\"{name} - {group.name}\"\n\n        return super().__str__()\n", "path": "src/products/models/course.py"}]}