prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Sponsors with multiple packages are listed for each package
  When a sponsor takes multiple packages (sponsorship and add-on package, for example), they are listed in the sponsor list and sponsor menu for each package, which is a bit surprising. See Microsoft from PyCon ZA 2018, for example.
  
  ![microsoft_multiple](https://user-images.githubusercontent.com/642056/47145177-6b953480-d2c9-11e8-9ed4-c19440cd0cb7.png)
  
  
  We should list sponsors only once, and add some decent way of marking that sponsors have taken multiple packages in the list.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `wafer/sponsors/models.py`
  Content:
  ```
  1 # -*- coding: utf-8 -*-
  2 
  3 import logging
  4 
  5 from django.core.validators import MinValueValidator
  6 from django.db import models
  7 from django.db.models.signals import post_save
  8 from django.urls import reverse
  9 from django.utils.encoding import python_2_unicode_compatible
  10 from django.utils.translation import ugettext_lazy as _
  11 
  12 from markitup.fields import MarkupField
  13 
  14 from wafer.menu import menu_logger, refresh_menu_cache
  15 
  16 logger = logging.getLogger(__name__)
  17 
  18 
  19 @python_2_unicode_compatible
  20 class File(models.Model):
  21     """A file for use in sponsor and sponshorship package descriptions."""
  22     name = models.CharField(max_length=255)
  23     description = models.TextField(blank=True)
  24     item = models.FileField(upload_to='sponsors_files')
  25 
  26     def __str__(self):
  27         return u'%s (%s)' % (self.name, self.item.url)
  28 
  29 
  30 @python_2_unicode_compatible
  31 class SponsorshipPackage(models.Model):
  32     """A description of a sponsorship package."""
  33     order = models.IntegerField(default=1)
  34     name = models.CharField(max_length=255)
  35     number_available = models.IntegerField(
  36         null=True, validators=[MinValueValidator(0)])
  37     currency = models.CharField(
  38         max_length=16, default='$',
  39         help_text=_("Currency symbol for the sponsorship amount."))
  40     price = models.DecimalField(
  41         max_digits=12, decimal_places=2,
  42         help_text=_("Amount to be sponsored."))
  43     short_description = models.TextField(
  44         help_text=_("One sentence overview of the package."))
  45     description = MarkupField(
  46         help_text=_("Describe what the package gives the sponsor."))
  47     files = models.ManyToManyField(
  48         File, related_name="packages", blank=True,
  49         help_text=_("Images and other files for use in"
  50                     " the description markdown field."))
  51     # We use purely ascii help text, to avoid issues with the migrations
  52     # not handling unicode help text nicely.
  53     symbol = models.CharField(
  54         max_length=1, blank=True,
  55         help_text=_("Optional symbol to display in the sponsors list "
  56                     "next to sponsors who have sponsored at this list, "
  57                     "(for example *)."))
  58 
  59     class Meta:
  60         ordering = ['order', '-price', 'name']
  61 
  62     def __str__(self):
  63         return u'%s (amount: %.0f)' % (self.name, self.price)
  64 
  65     def number_claimed(self):
  66         return self.sponsors.count()
  67 
  68 
  69 @python_2_unicode_compatible
  70 class Sponsor(models.Model):
  71     """A conference sponsor."""
  72     order = models.IntegerField(default=1)
  73     name = models.CharField(max_length=255)
  74     packages = models.ManyToManyField(SponsorshipPackage,
  75                                       related_name="sponsors")
  76     description = MarkupField(
  77         help_text=_("Write some nice things about the sponsor."))
  78     url = models.URLField(
  79         default="", blank=True,
  80         help_text=_("Url to link back to the sponsor if required"))
  81 
  82     class Meta:
  83         ordering = ['order', 'name', 'id']
  84 
  85     def __str__(self):
  86         return u'%s' % (self.name,)
  87 
  88     def get_absolute_url(self):
  89         return reverse('wafer_sponsor', args=(self.pk,))
  90 
  91     def symbols(self):
  92         """Return a string of the symbols of all the packages this sponsor has
  93            taken."""
  94         packages = self.packages.all()
  95         symbols = u"".join(p.symbol for p in packages)
  96         return symbols
  97 
  98     @property
  99     def symbol(self):
  100         """The symbol of the highest level package this sponsor has taken."""
  101         package = self.packages.first()
  102         if package:
  103             return package.symbol
  104         return u""
  105 
  106 
  107 class TaggedFile(models.Model):
  108     """Tags for files associated with a given sponsor"""
  109     tag_name = models.CharField(max_length=255, null=False)
  110     tagged_file = models.ForeignKey(File, on_delete=models.CASCADE)
  111     sponsor = models.ForeignKey(Sponsor, related_name="files",
  112                                 on_delete=models.CASCADE)
  113 
  114 
  115 def sponsor_menu(
  116         root_menu, menu="sponsors", label=_("Sponsors"),
  117         sponsors_item=_("Our sponsors"),
  118         packages_item=_("Sponsorship packages")):
  119     """Add sponsor menu links."""
  120     root_menu.add_menu(menu, label, items=[])
  121     for sponsor in (
  122             Sponsor.objects.all()
  123             .order_by('packages', 'order', 'id')
  124             .prefetch_related('packages')):
  125         symbols = sponsor.symbols()
  126         if symbols:
  127             item_name = u"» %s %s" % (sponsor.name, symbols)
  128         else:
  129             item_name = u"» %s" % (sponsor.name,)
  130         with menu_logger(logger, "sponsor %r" % (sponsor.name,)):
  131             root_menu.add_item(
  132                 item_name, sponsor.get_absolute_url(), menu=menu)
  133 
  134     if sponsors_item:
  135         with menu_logger(logger, "sponsors page link"):
  136             root_menu.add_item(
  137                 sponsors_item, reverse("wafer_sponsors"), menu)
  138     if packages_item:
  139         with menu_logger(logger, "sponsorship package page link"):
  140             root_menu.add_item(
  141                 packages_item, reverse("wafer_sponsorship_packages"), menu)
  142 
  143 
  144 post_save.connect(refresh_menu_cache, sender=Sponsor)
  145
  ```
  --- 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/wafer/sponsors/models.py b/wafer/sponsors/models.py
  --- a/wafer/sponsors/models.py
  +++ b/wafer/sponsors/models.py
  @@ -118,10 +118,15 @@
           packages_item=_("Sponsorship packages")):
       """Add sponsor menu links."""
       root_menu.add_menu(menu, label, items=[])
  +    added_to_menu = set()
       for sponsor in (
               Sponsor.objects.all()
               .order_by('packages', 'order', 'id')
               .prefetch_related('packages')):
  +        if sponsor in added_to_menu:
  +            # We've already added this in a previous packaged
  +            continue
  +        added_to_menu.add(sponsor)
           symbols = sponsor.symbols()
           if symbols:
               item_name = u"» %s %s" % (sponsor.name, symbols)
  
verification_info: {"golden_diff": "diff --git a/wafer/sponsors/models.py b/wafer/sponsors/models.py\n--- a/wafer/sponsors/models.py\n+++ b/wafer/sponsors/models.py\n@@ -118,10 +118,15 @@\n         packages_item=_(\"Sponsorship packages\")):\n     \"\"\"Add sponsor menu links.\"\"\"\n     root_menu.add_menu(menu, label, items=[])\n+    added_to_menu = set()\n     for sponsor in (\n             Sponsor.objects.all()\n             .order_by('packages', 'order', 'id')\n             .prefetch_related('packages')):\n+        if sponsor in added_to_menu:\n+            # We've already added this in a previous packaged\n+            continue\n+        added_to_menu.add(sponsor)\n         symbols = sponsor.symbols()\n         if symbols:\n             item_name = u\"\u00bb %s %s\" % (sponsor.name, symbols)\n", "issue": "Sponsors with multiple packages are listed for each package\nWhen a sponsor takes multiple packages (sponsorship and add-on package, for example), they are listed in the sponsor list and sponsor menu for each package, which is a bit surprising. See Microsoft from PyCon ZA 2018, for example.\r\n\r\n![microsoft_multiple](https://user-images.githubusercontent.com/642056/47145177-6b953480-d2c9-11e8-9ed4-c19440cd0cb7.png)\r\n\r\n\r\nWe should list sponsors only once, and add some decent way of marking that sponsors have taken multiple packages in the list.\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\nimport logging\n\nfrom django.core.validators import MinValueValidator\nfrom django.db import models\nfrom django.db.models.signals import post_save\nfrom django.urls import reverse\nfrom django.utils.encoding import python_2_unicode_compatible\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom markitup.fields import MarkupField\n\nfrom wafer.menu import menu_logger, refresh_menu_cache\n\nlogger = logging.getLogger(__name__)\n\n\n@python_2_unicode_compatible\nclass File(models.Model):\n    \"\"\"A file for use in sponsor and sponshorship package descriptions.\"\"\"\n    name = models.CharField(max_length=255)\n    description = models.TextField(blank=True)\n    item = models.FileField(upload_to='sponsors_files')\n\n    def __str__(self):\n        return u'%s (%s)' % (self.name, self.item.url)\n\n\n@python_2_unicode_compatible\nclass SponsorshipPackage(models.Model):\n    \"\"\"A description of a sponsorship package.\"\"\"\n    order = models.IntegerField(default=1)\n    name = models.CharField(max_length=255)\n    number_available = models.IntegerField(\n        null=True, validators=[MinValueValidator(0)])\n    currency = models.CharField(\n        max_length=16, default='$',\n        help_text=_(\"Currency symbol for the sponsorship amount.\"))\n    price = models.DecimalField(\n        max_digits=12, decimal_places=2,\n        help_text=_(\"Amount to be sponsored.\"))\n    short_description = models.TextField(\n        help_text=_(\"One sentence overview of the package.\"))\n    description = MarkupField(\n        help_text=_(\"Describe what the package gives the sponsor.\"))\n    files = models.ManyToManyField(\n        File, related_name=\"packages\", blank=True,\n        help_text=_(\"Images and other files for use in\"\n                    \" the description markdown field.\"))\n    # We use purely ascii help text, to avoid issues with the migrations\n    # not handling unicode help text nicely.\n    symbol = models.CharField(\n        max_length=1, blank=True,\n        help_text=_(\"Optional symbol to display in the sponsors list \"\n                    \"next to sponsors who have sponsored at this list, \"\n                    \"(for example *).\"))\n\n    class Meta:\n        ordering = ['order', '-price', 'name']\n\n    def __str__(self):\n        return u'%s (amount: %.0f)' % (self.name, self.price)\n\n    def number_claimed(self):\n        return self.sponsors.count()\n\n\n@python_2_unicode_compatible\nclass Sponsor(models.Model):\n    \"\"\"A conference sponsor.\"\"\"\n    order = models.IntegerField(default=1)\n    name = models.CharField(max_length=255)\n    packages = models.ManyToManyField(SponsorshipPackage,\n                                      related_name=\"sponsors\")\n    description = MarkupField(\n        help_text=_(\"Write some nice things about the sponsor.\"))\n    url = models.URLField(\n        default=\"\", blank=True,\n        help_text=_(\"Url to link back to the sponsor if required\"))\n\n    class Meta:\n        ordering = ['order', 'name', 'id']\n\n    def __str__(self):\n        return u'%s' % (self.name,)\n\n    def get_absolute_url(self):\n        return reverse('wafer_sponsor', args=(self.pk,))\n\n    def symbols(self):\n        \"\"\"Return a string of the symbols of all the packages this sponsor has\n           taken.\"\"\"\n        packages = self.packages.all()\n        symbols = u\"\".join(p.symbol for p in packages)\n        return symbols\n\n    @property\n    def symbol(self):\n        \"\"\"The symbol of the highest level package this sponsor has taken.\"\"\"\n        package = self.packages.first()\n        if package:\n            return package.symbol\n        return u\"\"\n\n\nclass TaggedFile(models.Model):\n    \"\"\"Tags for files associated with a given sponsor\"\"\"\n    tag_name = models.CharField(max_length=255, null=False)\n    tagged_file = models.ForeignKey(File, on_delete=models.CASCADE)\n    sponsor = models.ForeignKey(Sponsor, related_name=\"files\",\n                                on_delete=models.CASCADE)\n\n\ndef sponsor_menu(\n        root_menu, menu=\"sponsors\", label=_(\"Sponsors\"),\n        sponsors_item=_(\"Our sponsors\"),\n        packages_item=_(\"Sponsorship packages\")):\n    \"\"\"Add sponsor menu links.\"\"\"\n    root_menu.add_menu(menu, label, items=[])\n    for sponsor in (\n            Sponsor.objects.all()\n            .order_by('packages', 'order', 'id')\n            .prefetch_related('packages')):\n        symbols = sponsor.symbols()\n        if symbols:\n            item_name = u\"\u00bb %s %s\" % (sponsor.name, symbols)\n        else:\n            item_name = u\"\u00bb %s\" % (sponsor.name,)\n        with menu_logger(logger, \"sponsor %r\" % (sponsor.name,)):\n            root_menu.add_item(\n                item_name, sponsor.get_absolute_url(), menu=menu)\n\n    if sponsors_item:\n        with menu_logger(logger, \"sponsors page link\"):\n            root_menu.add_item(\n                sponsors_item, reverse(\"wafer_sponsors\"), menu)\n    if packages_item:\n        with menu_logger(logger, \"sponsorship package page link\"):\n            root_menu.add_item(\n                packages_item, reverse(\"wafer_sponsorship_packages\"), menu)\n\n\npost_save.connect(refresh_menu_cache, sender=Sponsor)\n", "path": "wafer/sponsors/models.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\nimport logging\n\nfrom django.core.validators import MinValueValidator\nfrom django.db import models\nfrom django.db.models.signals import post_save\nfrom django.urls import reverse\nfrom django.utils.encoding import python_2_unicode_compatible\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom markitup.fields import MarkupField\n\nfrom wafer.menu import menu_logger, refresh_menu_cache\n\nlogger = logging.getLogger(__name__)\n\n\n@python_2_unicode_compatible\nclass File(models.Model):\n    \"\"\"A file for use in sponsor and sponshorship package descriptions.\"\"\"\n    name = models.CharField(max_length=255)\n    description = models.TextField(blank=True)\n    item = models.FileField(upload_to='sponsors_files')\n\n    def __str__(self):\n        return u'%s (%s)' % (self.name, self.item.url)\n\n\n@python_2_unicode_compatible\nclass SponsorshipPackage(models.Model):\n    \"\"\"A description of a sponsorship package.\"\"\"\n    order = models.IntegerField(default=1)\n    name = models.CharField(max_length=255)\n    number_available = models.IntegerField(\n        null=True, validators=[MinValueValidator(0)])\n    currency = models.CharField(\n        max_length=16, default='$',\n        help_text=_(\"Currency symbol for the sponsorship amount.\"))\n    price = models.DecimalField(\n        max_digits=12, decimal_places=2,\n        help_text=_(\"Amount to be sponsored.\"))\n    short_description = models.TextField(\n        help_text=_(\"One sentence overview of the package.\"))\n    description = MarkupField(\n        help_text=_(\"Describe what the package gives the sponsor.\"))\n    files = models.ManyToManyField(\n        File, related_name=\"packages\", blank=True,\n        help_text=_(\"Images and other files for use in\"\n                    \" the description markdown field.\"))\n    # We use purely ascii help text, to avoid issues with the migrations\n    # not handling unicode help text nicely.\n    symbol = models.CharField(\n        max_length=1, blank=True,\n        help_text=_(\"Optional symbol to display in the sponsors list \"\n                    \"next to sponsors who have sponsored at this list, \"\n                    \"(for example *).\"))\n\n    class Meta:\n        ordering = ['order', '-price', 'name']\n\n    def __str__(self):\n        return u'%s (amount: %.0f)' % (self.name, self.price)\n\n    def number_claimed(self):\n        return self.sponsors.count()\n\n\n@python_2_unicode_compatible\nclass Sponsor(models.Model):\n    \"\"\"A conference sponsor.\"\"\"\n    order = models.IntegerField(default=1)\n    name = models.CharField(max_length=255)\n    packages = models.ManyToManyField(SponsorshipPackage,\n                                      related_name=\"sponsors\")\n    description = MarkupField(\n        help_text=_(\"Write some nice things about the sponsor.\"))\n    url = models.URLField(\n        default=\"\", blank=True,\n        help_text=_(\"Url to link back to the sponsor if required\"))\n\n    class Meta:\n        ordering = ['order', 'name', 'id']\n\n    def __str__(self):\n        return u'%s' % (self.name,)\n\n    def get_absolute_url(self):\n        return reverse('wafer_sponsor', args=(self.pk,))\n\n    def symbols(self):\n        \"\"\"Return a string of the symbols of all the packages this sponsor has\n           taken.\"\"\"\n        packages = self.packages.all()\n        symbols = u\"\".join(p.symbol for p in packages)\n        return symbols\n\n    @property\n    def symbol(self):\n        \"\"\"The symbol of the highest level package this sponsor has taken.\"\"\"\n        package = self.packages.first()\n        if package:\n            return package.symbol\n        return u\"\"\n\n\nclass TaggedFile(models.Model):\n    \"\"\"Tags for files associated with a given sponsor\"\"\"\n    tag_name = models.CharField(max_length=255, null=False)\n    tagged_file = models.ForeignKey(File, on_delete=models.CASCADE)\n    sponsor = models.ForeignKey(Sponsor, related_name=\"files\",\n                                on_delete=models.CASCADE)\n\n\ndef sponsor_menu(\n        root_menu, menu=\"sponsors\", label=_(\"Sponsors\"),\n        sponsors_item=_(\"Our sponsors\"),\n        packages_item=_(\"Sponsorship packages\")):\n    \"\"\"Add sponsor menu links.\"\"\"\n    root_menu.add_menu(menu, label, items=[])\n    added_to_menu = set()\n    for sponsor in (\n            Sponsor.objects.all()\n            .order_by('packages', 'order', 'id')\n            .prefetch_related('packages')):\n        if sponsor in added_to_menu:\n            # We've already added this in a previous packaged\n            continue\n        added_to_menu.add(sponsor)\n        symbols = sponsor.symbols()\n        if symbols:\n            item_name = u\"\u00bb %s %s\" % (sponsor.name, symbols)\n        else:\n            item_name = u\"\u00bb %s\" % (sponsor.name,)\n        with menu_logger(logger, \"sponsor %r\" % (sponsor.name,)):\n            root_menu.add_item(\n                item_name, sponsor.get_absolute_url(), menu=menu)\n\n    if sponsors_item:\n        with menu_logger(logger, \"sponsors page link\"):\n            root_menu.add_item(\n                sponsors_item, reverse(\"wafer_sponsors\"), menu)\n    if packages_item:\n        with menu_logger(logger, \"sponsorship package page link\"):\n            root_menu.add_item(\n                packages_item, reverse(\"wafer_sponsorship_packages\"), menu)\n\n\npost_save.connect(refresh_menu_cache, sender=Sponsor)\n", "path": "wafer/sponsors/models.py"}]}