We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Cannot add new sponsor
I tried adding new sponsors to the QGIS sponsors list, but got the following error:

500
Ooops. Something broke....

The powers that be have been informed.
In the meantime, please form an orderly queue and head to the home page.

If you need assistance, you may reference this error as 1f96dfdab8c642789dcb40867a97e90d.

I used foreign characters, f.e. "ü" and "é" in the contact names, if that matters.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `django_project/base/models/project.py`
Content:
```
1 # coding=utf-8
2 """Project model used by all apps."""
3 import os
4 import logging
5 import string
6 import re
7 from django.core.urlresolvers import reverse
8 from django.utils.text import slugify
9 from django.conf.global_settings import MEDIA_ROOT
10 from django.db import models
11 from django.utils.translation import ugettext_lazy as _
12 from changes.models.version import Version
13 from core.settings.contrib import STOP_WORDS
14 from django.contrib.auth.models import User
15 from django.conf import settings
16 from django.core.exceptions import ValidationError
17 
18 logger = logging.getLogger(__name__)
19 
20 
21 class ApprovedProjectManager(models.Manager):
22     """Custom project manager that shows only approved records."""
23 
24     def get_queryset(self):
25         """Query set generator"""
26         return super(
27             ApprovedProjectManager, self).get_queryset().filter(
28                 approved=True)
29 
30 
31 class UnapprovedProjectManager(models.Manager):
32     """Custom project manager that shows only unapproved records."""
33 
34     def get_queryset(self):
35         """Query set generator"""
36         return super(
37             UnapprovedProjectManager, self).get_queryset().filter(
38                 approved=False)
39 
40 
41 class PublicProjectManager(models.Manager):
42     """Custom project manager that shows only public and approved projects."""
43 
44     def get_queryset(self):
45         """Query set generator"""
46         return super(
47             PublicProjectManager, self).get_queryset().filter(
48                 private=False).filter(approved=True)
49 
50 
51 def validate_gitter_room_name(value):
52     """Ensure user enter proper gitter room name
53 
54     :param value: string input
55     :raises: ValidationError
56     """
57     invalid_chars = set(string.punctuation.replace('/', ''))
58     pattern = re.compile('^(\w+\/\w+)$')
59     if any(char in invalid_chars for char in value) \
60             or not pattern.match(value):
61         raise ValidationError(
62             _('%(value)s is not proper gitter room name'),
63             params={'value': value},
64         )
65 
66 
67 class Project(models.Model):
68     """A project model e.g. QGIS, InaSAFE etc."""
69     name = models.CharField(
70         help_text=_('Name of this project.'),
71         max_length=255,
72         null=False,
73         blank=False,
74         unique=True)
75 
76     description = models.CharField(
77         help_text=_('A description for the project'),
78         max_length=500,
79         blank=True,
80         null=True
81     )
82 
83     image_file = models.ImageField(
84         help_text=_('A logo image for this project. '
85                     'Most browsers support dragging the image directly on to '
86                     'the "Choose File" button above.'),
87         upload_to=os.path.join(MEDIA_ROOT, 'images/projects'),
88         blank=True
89     )
90 
91     approved = models.BooleanField(
92         help_text=_('Whether this project has been approved for use yet.'),
93         default=False
94     )
95 
96     private = models.BooleanField(
97         help_text=_('Only visible to logged-in users?'),
98         default=False
99     )
100 
101     owner = models.ForeignKey(User)
102     slug = models.SlugField(unique=True)
103     objects = models.Manager()
104     approved_objects = ApprovedProjectManager()
105     unapproved_objects = UnapprovedProjectManager()
106     public_objects = PublicProjectManager()
107 
108     gitter_room = models.CharField(
109         help_text=_('Gitter room name, e.g. gitterhq/sandbox'),
110         max_length=255,
111         null=True,
112         blank=True,
113         validators=[validate_gitter_room_name]
114     )
115 
116     # noinspection PyClassicStyleClass
117     class Meta:
118         """Meta class for project."""
119         app_label = 'base'
120         ordering = ['name']
121 
122     def save(self, *args, **kwargs):
123         """Overloaded save method.
124 
125         :param args:
126         :param kwargs:
127         """
128         if not self.pk:
129             words = self.name.split()
130             filtered_words = [t for t in words if t.lower() not in STOP_WORDS]
131             new_list = unicode(' '.join(filtered_words))
132             self.slug = slugify(new_list)[:50]
133 
134         super(Project, self).save(*args, **kwargs)
135 
136     def __unicode__(self):
137         return u'%s' % self.name
138 
139     def get_absolute_url(self):
140         """Return URL to project detail page
141 
142         :return: URL
143         :rtype: str
144 
145         """
146         return reverse('project-detail', kwargs={'slug': self.slug})
147 
148     def versions(self):
149         """Get all the versions for this project."""
150         qs = Version.objects.filter(project=self).order_by('-padded_version')
151         return qs
152 
153     def latest_versions(self):
154         """Get the latest version.
155 
156         How many versions returned is determined by the pagination threshold.
157 
158         :returns: List of versions.
159         :rtype: list"""
160         return self.versions()[:settings.PROJECT_VERSION_LIST_SIZE]
161 
162     @staticmethod
163     def pagination_threshold(self):
164         """Find out how many versions to list per page.
165 
166         :returns: The count of items to show per page as defined in
167             settings.PROJECT_VERSION_LIST_SIZE.
168         :rtype: int
169         """
170         return settings.PROJECT_VERSION_LIST_SIZE
171 
172     def pagination_threshold_exceeded(self):
173         """Check if project version count exceeds pagination threshold.
174 
175         :returns: Flag indicating if there are more versions than
176             self.threshold.
177         :rtype: bool
178         """
179         if self.versions().count() >= settings.PROJECT_VERSION_LIST_SIZE:
180             return True
181         else:
182             return False
183
```

Path: `django_project/changes/models/sponsor.py`
Content:
```
1 # coding=utf-8
2 import os
3 import pytz
4 import logging
5 from django.core.urlresolvers import reverse
6 from django.utils.text import slugify
7 from core.settings.contrib import STOP_WORDS
8 from django.conf.global_settings import MEDIA_ROOT
9 from django.db import models
10 from django.utils.translation import ugettext_lazy as _
11 from django.contrib.auth.models import User
12 from django_countries.fields import CountryField
13 
14 __author__ = 'rischan'
15 
16 logger = logging.getLogger(__name__)
17 utc = pytz.UTC
18 
19 
20 class ApprovedSponsorManager(models.Manager):
21     """Custom sponsor manager that shows only approved records."""
22 
23     def get_queryset(self):
24         """Query set generator"""
25         return super(
26             ApprovedSponsorManager, self).get_queryset().filter(
27                 approved=True)
28 
29 
30 class UnapprovedSponsorManager(models.Manager):
31     """Custom sponsor manager that shows only unapproved records."""
32 
33     def get_queryset(self):
34         """Query set generator"""
35         return super(
36             UnapprovedSponsorManager, self).get_queryset().filter(
37                 approved=False)
38 
39 
40 # noinspection PyUnresolvedReferences
41 class Sponsor(models.Model):
42     """A sponsor model e.g. gui, backend, web site etc."""
43     name = models.CharField(
44         help_text=_('Name of sponsor.'),
45         max_length=255,
46         null=False,
47         blank=False,
48         unique=False)  # there is a unique together rule in meta class below
49 
50     sponsor_url = models.CharField(
51         help_text='Input the sponsor URL.',
52         max_length=255,
53         null=True,
54         blank=True)
55 
56     contact_person = models.CharField(
57         help_text='Input the contact person of sponsor.',
58         max_length=255,
59         null=True,
60         blank=True)
61 
62     address = models.TextField(
63         help_text=(
64             'Enter the complete street address for this sponsor. '
65             'Use line breaks to separate address elements and use '
66             'the country field to specify the country.'
67         ),
68         null=True,
69         blank=True)
70 
71     country = CountryField(
72         help_text='Select the country for this sponsor',
73         null=True,
74         blank=True)
75 
76     sponsor_email = models.CharField(
77         help_text='Input an email of sponsor.',
78         max_length=255,
79         null=True,
80         blank=True)
81 
82     agreement = models.FileField(
83         help_text='Attach sponsor agreement',
84         upload_to=os.path.join(MEDIA_ROOT, 'docs'),
85         blank=True)
86 
87     logo = models.ImageField(
88         help_text=(
89             'An image of sponsor logo e.g. a splashscreen. '
90             'Most browsers support dragging the image directly on to the '
91             '"Choose File" button above.'),
92         upload_to=os.path.join(MEDIA_ROOT, 'images/projects'),
93         blank=False)
94 
95     approved = models.BooleanField(
96         help_text=_(
97             'Whether this sponsor has been approved for use by the '
98             'project owner.'),
99         default=False
100     )
101 
102     author = models.ForeignKey(User)
103     slug = models.SlugField()
104     project = models.ForeignKey('base.Project')
105     objects = models.Manager()
106     approved_objects = ApprovedSponsorManager()
107     unapproved_objects = UnapprovedSponsorManager()
108 
109     # noinspection PyClassicStyleClass
110     class Meta:
111         """Meta options for the sponsor class."""
112         unique_together = (
113             ('name', 'project'),
114             ('project', 'slug')
115         )
116         app_label = 'changes'
117         ordering = ['name']
118 
119     def save(self, *args, **kwargs):
120         if not self.pk:
121             words = self.name.split()
122             filtered_words = [t for t in words if t.lower() not in STOP_WORDS]
123             new_list = ' '.join(filtered_words)
124             self.slug = slugify(new_list)[:50]
125         super(Sponsor, self).save(*args, **kwargs)
126 
127     def __unicode__(self):
128         return u'%s' % (self.name)
129 
130     def get_absolute_url(self):
131         return reverse('sponsor-detail', kwargs={
132             'slug': self.slug,
133             'project_slug': self.project.slug
134         })
135
```
--- 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/django_project/base/models/project.py b/django_project/base/models/project.py
--- a/django_project/base/models/project.py
+++ b/django_project/base/models/project.py
@@ -14,6 +14,7 @@
 from django.contrib.auth.models import User
 from django.conf import settings
 from django.core.exceptions import ValidationError
+from unidecode import unidecode
 
 logger = logging.getLogger(__name__)
 
@@ -128,7 +129,8 @@
         if not self.pk:
             words = self.name.split()
             filtered_words = [t for t in words if t.lower() not in STOP_WORDS]
-            new_list = unicode(' '.join(filtered_words))
+            # unidecode() represents special characters (unicode data) in ASCII
+            new_list = unidecode(' '.join(filtered_words))
             self.slug = slugify(new_list)[:50]
 
         super(Project, self).save(*args, **kwargs)
diff --git a/django_project/changes/models/sponsor.py b/django_project/changes/models/sponsor.py
--- a/django_project/changes/models/sponsor.py
+++ b/django_project/changes/models/sponsor.py
@@ -10,6 +10,8 @@
 from django.utils.translation import ugettext_lazy as _
 from django.contrib.auth.models import User
 from django_countries.fields import CountryField
+from unidecode import unidecode
+
 
 __author__ = 'rischan'
 
@@ -120,7 +122,8 @@
         if not self.pk:
             words = self.name.split()
             filtered_words = [t for t in words if t.lower() not in STOP_WORDS]
-            new_list = ' '.join(filtered_words)
+            # unidecode() represents special characters (unicode data) in ASCII
+            new_list = unidecode(' '.join(filtered_words))
             self.slug = slugify(new_list)[:50]
         super(Sponsor, self).save(*args, **kwargs)

{"golden_diff": "diff --git a/django_project/base/models/project.py b/django_project/base/models/project.py\n--- a/django_project/base/models/project.py\n+++ b/django_project/base/models/project.py\n@@ -14,6 +14,7 @@\n from django.contrib.auth.models import User\n from django.conf import settings\n from django.core.exceptions import ValidationError\n+from unidecode import unidecode\n \n logger = logging.getLogger(__name__)\n \n@@ -128,7 +129,8 @@\n         if not self.pk:\n             words = self.name.split()\n             filtered_words = [t for t in words if t.lower() not in STOP_WORDS]\n-            new_list = unicode(' '.join(filtered_words))\n+            # unidecode() represents special characters (unicode data) in ASCII\n+            new_list = unidecode(' '.join(filtered_words))\n             self.slug = slugify(new_list)[:50]\n \n         super(Project, self).save(*args, **kwargs)\ndiff --git a/django_project/changes/models/sponsor.py b/django_project/changes/models/sponsor.py\n--- a/django_project/changes/models/sponsor.py\n+++ b/django_project/changes/models/sponsor.py\n@@ -10,6 +10,8 @@\n from django.utils.translation import ugettext_lazy as _\n from django.contrib.auth.models import User\n from django_countries.fields import CountryField\n+from unidecode import unidecode\n+\n \n __author__ = 'rischan'\n \n@@ -120,7 +122,8 @@\n         if not self.pk:\n             words = self.name.split()\n             filtered_words = [t for t in words if t.lower() not in STOP_WORDS]\n-            new_list = ' '.join(filtered_words)\n+            # unidecode() represents special characters (unicode data) in ASCII\n+            new_list = unidecode(' '.join(filtered_words))\n             self.slug = slugify(new_list)[:50]\n         super(Sponsor, self).save(*args, **kwargs)\n", "issue": "Cannot add new sponsor\nI tried adding new sponsors to the QGIS sponsors list, but got the following error:\n\n500\nOoops. Something broke....\n\nThe powers that be have been informed.\nIn the meantime, please form an orderly queue and head to the home page.\n\nIf you need assistance, you may reference this error as 1f96dfdab8c642789dcb40867a97e90d.\n\nI used foreign characters, f.e. \"\u00fc\" and \"\u00e9\" in the contact names, if that matters.\n\n", "before_files": [{"content": "# coding=utf-8\n\"\"\"Project model used by all apps.\"\"\"\nimport os\nimport logging\nimport string\nimport re\nfrom django.core.urlresolvers import reverse\nfrom django.utils.text import slugify\nfrom django.conf.global_settings import MEDIA_ROOT\nfrom django.db import models\nfrom django.utils.translation import ugettext_lazy as _\nfrom changes.models.version import Version\nfrom core.settings.contrib import STOP_WORDS\nfrom django.contrib.auth.models import User\nfrom django.conf import settings\nfrom django.core.exceptions import ValidationError\n\nlogger = logging.getLogger(__name__)\n\n\nclass ApprovedProjectManager(models.Manager):\n    \"\"\"Custom project manager that shows only approved records.\"\"\"\n\n    def get_queryset(self):\n        \"\"\"Query set generator\"\"\"\n        return super(\n            ApprovedProjectManager, self).get_queryset().filter(\n                approved=True)\n\n\nclass UnapprovedProjectManager(models.Manager):\n    \"\"\"Custom project manager that shows only unapproved records.\"\"\"\n\n    def get_queryset(self):\n        \"\"\"Query set generator\"\"\"\n        return super(\n            UnapprovedProjectManager, self).get_queryset().filter(\n                approved=False)\n\n\nclass PublicProjectManager(models.Manager):\n    \"\"\"Custom project manager that shows only public and approved projects.\"\"\"\n\n    def get_queryset(self):\n        \"\"\"Query set generator\"\"\"\n        return super(\n            PublicProjectManager, self).get_queryset().filter(\n                private=False).filter(approved=True)\n\n\ndef validate_gitter_room_name(value):\n    \"\"\"Ensure user enter proper gitter room name\n\n    :param value: string input\n    :raises: ValidationError\n    \"\"\"\n    invalid_chars = set(string.punctuation.replace('/', ''))\n    pattern = re.compile('^(\\w+\\/\\w+)$')\n    if any(char in invalid_chars for char in value) \\\n            or not pattern.match(value):\n        raise ValidationError(\n            _('%(value)s is not proper gitter room name'),\n            params={'value': value},\n        )\n\n\nclass Project(models.Model):\n    \"\"\"A project model e.g. QGIS, InaSAFE etc.\"\"\"\n    name = models.CharField(\n        help_text=_('Name of this project.'),\n        max_length=255,\n        null=False,\n        blank=False,\n        unique=True)\n\n    description = models.CharField(\n        help_text=_('A description for the project'),\n        max_length=500,\n        blank=True,\n        null=True\n    )\n\n    image_file = models.ImageField(\n        help_text=_('A logo image for this project. '\n                    'Most browsers support dragging the image directly on to '\n                    'the \"Choose File\" button above.'),\n        upload_to=os.path.join(MEDIA_ROOT, 'images/projects'),\n        blank=True\n    )\n\n    approved = models.BooleanField(\n        help_text=_('Whether this project has been approved for use yet.'),\n        default=False\n    )\n\n    private = models.BooleanField(\n        help_text=_('Only visible to logged-in users?'),\n        default=False\n    )\n\n    owner = models.ForeignKey(User)\n    slug = models.SlugField(unique=True)\n    objects = models.Manager()\n    approved_objects = ApprovedProjectManager()\n    unapproved_objects = UnapprovedProjectManager()\n    public_objects = PublicProjectManager()\n\n    gitter_room = models.CharField(\n        help_text=_('Gitter room name, e.g. gitterhq/sandbox'),\n        max_length=255,\n        null=True,\n        blank=True,\n        validators=[validate_gitter_room_name]\n    )\n\n    # noinspection PyClassicStyleClass\n    class Meta:\n        \"\"\"Meta class for project.\"\"\"\n        app_label = 'base'\n        ordering = ['name']\n\n    def save(self, *args, **kwargs):\n        \"\"\"Overloaded save method.\n\n        :param args:\n        :param kwargs:\n        \"\"\"\n        if not self.pk:\n            words = self.name.split()\n            filtered_words = [t for t in words if t.lower() not in STOP_WORDS]\n            new_list = unicode(' '.join(filtered_words))\n            self.slug = slugify(new_list)[:50]\n\n        super(Project, self).save(*args, **kwargs)\n\n    def __unicode__(self):\n        return u'%s' % self.name\n\n    def get_absolute_url(self):\n        \"\"\"Return URL to project detail page\n\n        :return: URL\n        :rtype: str\n\n        \"\"\"\n        return reverse('project-detail', kwargs={'slug': self.slug})\n\n    def versions(self):\n        \"\"\"Get all the versions for this project.\"\"\"\n        qs = Version.objects.filter(project=self).order_by('-padded_version')\n        return qs\n\n    def latest_versions(self):\n        \"\"\"Get the latest version.\n\n        How many versions returned is determined by the pagination threshold.\n\n        :returns: List of versions.\n        :rtype: list\"\"\"\n        return self.versions()[:settings.PROJECT_VERSION_LIST_SIZE]\n\n    @staticmethod\n    def pagination_threshold(self):\n        \"\"\"Find out how many versions to list per page.\n\n        :returns: The count of items to show per page as defined in\n            settings.PROJECT_VERSION_LIST_SIZE.\n        :rtype: int\n        \"\"\"\n        return settings.PROJECT_VERSION_LIST_SIZE\n\n    def pagination_threshold_exceeded(self):\n        \"\"\"Check if project version count exceeds pagination threshold.\n\n        :returns: Flag indicating if there are more versions than\n            self.threshold.\n        :rtype: bool\n        \"\"\"\n        if self.versions().count() >= settings.PROJECT_VERSION_LIST_SIZE:\n            return True\n        else:\n            return False\n", "path": "django_project/base/models/project.py"}, {"content": "# coding=utf-8\nimport os\nimport pytz\nimport logging\nfrom django.core.urlresolvers import reverse\nfrom django.utils.text import slugify\nfrom core.settings.contrib import STOP_WORDS\nfrom django.conf.global_settings import MEDIA_ROOT\nfrom django.db import models\nfrom django.utils.translation import ugettext_lazy as _\nfrom django.contrib.auth.models import User\nfrom django_countries.fields import CountryField\n\n__author__ = 'rischan'\n\nlogger = logging.getLogger(__name__)\nutc = pytz.UTC\n\n\nclass ApprovedSponsorManager(models.Manager):\n    \"\"\"Custom sponsor manager that shows only approved records.\"\"\"\n\n    def get_queryset(self):\n        \"\"\"Query set generator\"\"\"\n        return super(\n            ApprovedSponsorManager, self).get_queryset().filter(\n                approved=True)\n\n\nclass UnapprovedSponsorManager(models.Manager):\n    \"\"\"Custom sponsor manager that shows only unapproved records.\"\"\"\n\n    def get_queryset(self):\n        \"\"\"Query set generator\"\"\"\n        return super(\n            UnapprovedSponsorManager, self).get_queryset().filter(\n                approved=False)\n\n\n# noinspection PyUnresolvedReferences\nclass Sponsor(models.Model):\n    \"\"\"A sponsor model e.g. gui, backend, web site etc.\"\"\"\n    name = models.CharField(\n        help_text=_('Name of sponsor.'),\n        max_length=255,\n        null=False,\n        blank=False,\n        unique=False)  # there is a unique together rule in meta class below\n\n    sponsor_url = models.CharField(\n        help_text='Input the sponsor URL.',\n        max_length=255,\n        null=True,\n        blank=True)\n\n    contact_person = models.CharField(\n        help_text='Input the contact person of sponsor.',\n        max_length=255,\n        null=True,\n        blank=True)\n\n    address = models.TextField(\n        help_text=(\n            'Enter the complete street address for this sponsor. '\n            'Use line breaks to separate address elements and use '\n            'the country field to specify the country.'\n        ),\n        null=True,\n        blank=True)\n\n    country = CountryField(\n        help_text='Select the country for this sponsor',\n        null=True,\n        blank=True)\n\n    sponsor_email = models.CharField(\n        help_text='Input an email of sponsor.',\n        max_length=255,\n        null=True,\n        blank=True)\n\n    agreement = models.FileField(\n        help_text='Attach sponsor agreement',\n        upload_to=os.path.join(MEDIA_ROOT, 'docs'),\n        blank=True)\n\n    logo = models.ImageField(\n        help_text=(\n            'An image of sponsor logo e.g. a splashscreen. '\n            'Most browsers support dragging the image directly on to the '\n            '\"Choose File\" button above.'),\n        upload_to=os.path.join(MEDIA_ROOT, 'images/projects'),\n        blank=False)\n\n    approved = models.BooleanField(\n        help_text=_(\n            'Whether this sponsor has been approved for use by the '\n            'project owner.'),\n        default=False\n    )\n\n    author = models.ForeignKey(User)\n    slug = models.SlugField()\n    project = models.ForeignKey('base.Project')\n    objects = models.Manager()\n    approved_objects = ApprovedSponsorManager()\n    unapproved_objects = UnapprovedSponsorManager()\n\n    # noinspection PyClassicStyleClass\n    class Meta:\n        \"\"\"Meta options for the sponsor class.\"\"\"\n        unique_together = (\n            ('name', 'project'),\n            ('project', 'slug')\n        )\n        app_label = 'changes'\n        ordering = ['name']\n\n    def save(self, *args, **kwargs):\n        if not self.pk:\n            words = self.name.split()\n            filtered_words = [t for t in words if t.lower() not in STOP_WORDS]\n            new_list = ' '.join(filtered_words)\n            self.slug = slugify(new_list)[:50]\n        super(Sponsor, self).save(*args, **kwargs)\n\n    def __unicode__(self):\n        return u'%s' % (self.name)\n\n    def get_absolute_url(self):\n        return reverse('sponsor-detail', kwargs={\n            'slug': self.slug,\n            'project_slug': self.project.slug\n        })\n", "path": "django_project/changes/models/sponsor.py"}], "after_files": [{"content": "# coding=utf-8\n\"\"\"Project model used by all apps.\"\"\"\nimport os\nimport logging\nimport string\nimport re\nfrom django.core.urlresolvers import reverse\nfrom django.utils.text import slugify\nfrom django.conf.global_settings import MEDIA_ROOT\nfrom django.db import models\nfrom django.utils.translation import ugettext_lazy as _\nfrom changes.models.version import Version\nfrom core.settings.contrib import STOP_WORDS\nfrom django.contrib.auth.models import User\nfrom django.conf import settings\nfrom django.core.exceptions import ValidationError\nfrom unidecode import unidecode\n\nlogger = logging.getLogger(__name__)\n\n\nclass ApprovedProjectManager(models.Manager):\n    \"\"\"Custom project manager that shows only approved records.\"\"\"\n\n    def get_queryset(self):\n        \"\"\"Query set generator\"\"\"\n        return super(\n            ApprovedProjectManager, self).get_queryset().filter(\n                approved=True)\n\n\nclass UnapprovedProjectManager(models.Manager):\n    \"\"\"Custom project manager that shows only unapproved records.\"\"\"\n\n    def get_queryset(self):\n        \"\"\"Query set generator\"\"\"\n        return super(\n            UnapprovedProjectManager, self).get_queryset().filter(\n                approved=False)\n\n\nclass PublicProjectManager(models.Manager):\n    \"\"\"Custom project manager that shows only public and approved projects.\"\"\"\n\n    def get_queryset(self):\n        \"\"\"Query set generator\"\"\"\n        return super(\n            PublicProjectManager, self).get_queryset().filter(\n                private=False).filter(approved=True)\n\n\ndef validate_gitter_room_name(value):\n    \"\"\"Ensure user enter proper gitter room name\n\n    :param value: string input\n    :raises: ValidationError\n    \"\"\"\n    invalid_chars = set(string.punctuation.replace('/', ''))\n    pattern = re.compile('^(\\w+\\/\\w+)$')\n    if any(char in invalid_chars for char in value) \\\n            or not pattern.match(value):\n        raise ValidationError(\n            _('%(value)s is not proper gitter room name'),\n            params={'value': value},\n        )\n\n\nclass Project(models.Model):\n    \"\"\"A project model e.g. QGIS, InaSAFE etc.\"\"\"\n    name = models.CharField(\n        help_text=_('Name of this project.'),\n        max_length=255,\n        null=False,\n        blank=False,\n        unique=True)\n\n    description = models.CharField(\n        help_text=_('A description for the project'),\n        max_length=500,\n        blank=True,\n        null=True\n    )\n\n    image_file = models.ImageField(\n        help_text=_('A logo image for this project. '\n                    'Most browsers support dragging the image directly on to '\n                    'the \"Choose File\" button above.'),\n        upload_to=os.path.join(MEDIA_ROOT, 'images/projects'),\n        blank=True\n    )\n\n    approved = models.BooleanField(\n        help_text=_('Whether this project has been approved for use yet.'),\n        default=False\n    )\n\n    private = models.BooleanField(\n        help_text=_('Only visible to logged-in users?'),\n        default=False\n    )\n\n    owner = models.ForeignKey(User)\n    slug = models.SlugField(unique=True)\n    objects = models.Manager()\n    approved_objects = ApprovedProjectManager()\n    unapproved_objects = UnapprovedProjectManager()\n    public_objects = PublicProjectManager()\n\n    gitter_room = models.CharField(\n        help_text=_('Gitter room name, e.g. gitterhq/sandbox'),\n        max_length=255,\n        null=True,\n        blank=True,\n        validators=[validate_gitter_room_name]\n    )\n\n    # noinspection PyClassicStyleClass\n    class Meta:\n        \"\"\"Meta class for project.\"\"\"\n        app_label = 'base'\n        ordering = ['name']\n\n    def save(self, *args, **kwargs):\n        \"\"\"Overloaded save method.\n\n        :param args:\n        :param kwargs:\n        \"\"\"\n        if not self.pk:\n            words = self.name.split()\n            filtered_words = [t for t in words if t.lower() not in STOP_WORDS]\n            # unidecode() represents special characters (unicode data) in ASCII\n            new_list = unidecode(' '.join(filtered_words))\n            self.slug = slugify(new_list)[:50]\n\n        super(Project, self).save(*args, **kwargs)\n\n    def __unicode__(self):\n        return u'%s' % self.name\n\n    def get_absolute_url(self):\n        \"\"\"Return URL to project detail page\n\n        :return: URL\n        :rtype: str\n\n        \"\"\"\n        return reverse('project-detail', kwargs={'slug': self.slug})\n\n    def versions(self):\n        \"\"\"Get all the versions for this project.\"\"\"\n        qs = Version.objects.filter(project=self).order_by('-padded_version')\n        return qs\n\n    def latest_versions(self):\n        \"\"\"Get the latest version.\n\n        How many versions returned is determined by the pagination threshold.\n\n        :returns: List of versions.\n        :rtype: list\"\"\"\n        return self.versions()[:settings.PROJECT_VERSION_LIST_SIZE]\n\n    @staticmethod\n    def pagination_threshold(self):\n        \"\"\"Find out how many versions to list per page.\n\n        :returns: The count of items to show per page as defined in\n            settings.PROJECT_VERSION_LIST_SIZE.\n        :rtype: int\n        \"\"\"\n        return settings.PROJECT_VERSION_LIST_SIZE\n\n    def pagination_threshold_exceeded(self):\n        \"\"\"Check if project version count exceeds pagination threshold.\n\n        :returns: Flag indicating if there are more versions than\n            self.threshold.\n        :rtype: bool\n        \"\"\"\n        if self.versions().count() >= settings.PROJECT_VERSION_LIST_SIZE:\n            return True\n        else:\n            return False\n", "path": "django_project/base/models/project.py"}, {"content": "# coding=utf-8\nimport os\nimport pytz\nimport logging\nfrom django.core.urlresolvers import reverse\nfrom django.utils.text import slugify\nfrom core.settings.contrib import STOP_WORDS\nfrom django.conf.global_settings import MEDIA_ROOT\nfrom django.db import models\nfrom django.utils.translation import ugettext_lazy as _\nfrom django.contrib.auth.models import User\nfrom django_countries.fields import CountryField\nfrom unidecode import unidecode\n\n\n__author__ = 'rischan'\n\nlogger = logging.getLogger(__name__)\nutc = pytz.UTC\n\n\nclass ApprovedSponsorManager(models.Manager):\n    \"\"\"Custom sponsor manager that shows only approved records.\"\"\"\n\n    def get_queryset(self):\n        \"\"\"Query set generator\"\"\"\n        return super(\n            ApprovedSponsorManager, self).get_queryset().filter(\n                approved=True)\n\n\nclass UnapprovedSponsorManager(models.Manager):\n    \"\"\"Custom sponsor manager that shows only unapproved records.\"\"\"\n\n    def get_queryset(self):\n        \"\"\"Query set generator\"\"\"\n        return super(\n            UnapprovedSponsorManager, self).get_queryset().filter(\n                approved=False)\n\n\n# noinspection PyUnresolvedReferences\nclass Sponsor(models.Model):\n    \"\"\"A sponsor model e.g. gui, backend, web site etc.\"\"\"\n    name = models.CharField(\n        help_text=_('Name of sponsor.'),\n        max_length=255,\n        null=False,\n        blank=False,\n        unique=False)  # there is a unique together rule in meta class below\n\n    sponsor_url = models.CharField(\n        help_text='Input the sponsor URL.',\n        max_length=255,\n        null=True,\n        blank=True)\n\n    contact_person = models.CharField(\n        help_text='Input the contact person of sponsor.',\n        max_length=255,\n        null=True,\n        blank=True)\n\n    address = models.TextField(\n        help_text=(\n            'Enter the complete street address for this sponsor. '\n            'Use line breaks to separate address elements and use '\n            'the country field to specify the country.'\n        ),\n        null=True,\n        blank=True)\n\n    country = CountryField(\n        help_text='Select the country for this sponsor',\n        null=True,\n        blank=True)\n\n    sponsor_email = models.CharField(\n        help_text='Input an email of sponsor.',\n        max_length=255,\n        null=True,\n        blank=True)\n\n    agreement = models.FileField(\n        help_text='Attach sponsor agreement',\n        upload_to=os.path.join(MEDIA_ROOT, 'docs'),\n        blank=True)\n\n    logo = models.ImageField(\n        help_text=(\n            'An image of sponsor logo e.g. a splashscreen. '\n            'Most browsers support dragging the image directly on to the '\n            '\"Choose File\" button above.'),\n        upload_to=os.path.join(MEDIA_ROOT, 'images/projects'),\n        blank=False)\n\n    approved = models.BooleanField(\n        help_text=_(\n            'Whether this sponsor has been approved for use by the '\n            'project owner.'),\n        default=False\n    )\n\n    author = models.ForeignKey(User)\n    slug = models.SlugField()\n    project = models.ForeignKey('base.Project')\n    objects = models.Manager()\n    approved_objects = ApprovedSponsorManager()\n    unapproved_objects = UnapprovedSponsorManager()\n\n    # noinspection PyClassicStyleClass\n    class Meta:\n        \"\"\"Meta options for the sponsor class.\"\"\"\n        unique_together = (\n            ('name', 'project'),\n            ('project', 'slug')\n        )\n        app_label = 'changes'\n        ordering = ['name']\n\n    def save(self, *args, **kwargs):\n        if not self.pk:\n            words = self.name.split()\n            filtered_words = [t for t in words if t.lower() not in STOP_WORDS]\n            # unidecode() represents special characters (unicode data) in ASCII\n            new_list = unidecode(' '.join(filtered_words))\n            self.slug = slugify(new_list)[:50]\n        super(Sponsor, self).save(*args, **kwargs)\n\n    def __unicode__(self):\n        return u'%s' % (self.name)\n\n    def get_absolute_url(self):\n        return reverse('sponsor-detail', kwargs={\n            'slug': self.slug,\n            'project_slug': self.project.slug\n        })\n", "path": "django_project/changes/models/sponsor.py"}]}