We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Is it possible to use the REST API to create and update a Project, with related resources, like Store, Translation Project, and Unit? 
I have spent considerable time now, trying to create a simple Project instance, using the REST API, but with no success so far.

Installed packages (pip freeze, with Python version 2.7.6):

```
Django==1.6.7
Pootle==2.6.0-rc2
South==1.0
argparse==1.2.1
cssmin==0.2.0
diff-match-patch==20121119
django-allauth==0.16.1
django-assets==0.10
django-contact-form==1.0
django-taggit==0.11.1
django-tastypie==0.12.0
django-voting==0.1
lxml==3.4.0
oauthlib==0.6.3
python-dateutil==2.2
python-memcached==1.53
python-mimeparse==0.1.4
python-openid==2.2.5
requests==2.4.3
requests-oauthlib==0.4.1
six==1.8.0
```

I use the the slumber library to access the API.  The following code

``` python
api = slumber.API('http://localhost:8000/api/v1/', auth=('admin', 'admin'))
api.projects.get()
```

returns the expected 

```
{'meta': {'limit': 1000,
  'next': None,
  'offset': 0,
  'previous': None,
  'total_count': 2},
 'objects': [{'backlink': 'http://localhost:8000/projects/terminology/',
   'checkstyle': 'terminology',
   'code': 'terminology',
   'description': u'',
   'fullname': 'Terminology',
   'ignoredfiles': u'',
   'localfiletype': 'po',
   'resource_uri': '/api/v1/projects/1/',
   'source_language': '/api/v1/languages/2/',
   'translation_projects': ['/api/v1/translation-projects/2/',
    '/api/v1/translation-projects/3/',
    # […]
    '/api/v1/translation-projects/62/',
    '/api/v1/translation-projects/63/'],
   'treestyle': 'auto'},
  {'backlink': 'http://localhost:8000/projects/tutorial/',
   'checkstyle': 'standard',
   'code': 'tutorial',
   'description': '<div dir="ltr" lang="en">Tutorial project where users can play with Pootle and learn more about translation and localisation.<br>For more help on localisation, visit the <a href="http://docs.translatehouse.org/projects/localization-guide/en/latest/guide/start.html">localisation guide</a>.</div>',
   'fullname': 'Tutorial',
   'ignoredfiles': u'',
   'localfiletype': 'po',
   'resource_uri': '/api/v1/projects/2/',
   'source_language': '/api/v1/languages/2/',
   'translation_projects': ['/api/v1/translation-projects/1/',
    '/api/v1/translation-projects/28/',
    '/api/v1/translation-projects/33/',
    '/api/v1/translation-projects/35/',
    '/api/v1/translation-projects/37/',
    '/api/v1/translation-projects/46/'],
   'treestyle': 'auto'}]}
```

While attempting the following code: 

``` python
fields = {
 'checkstyle': 'standard',
 'code': 'test01',
 'description': 'Another test.',
 'fullname': 'Test #01',
 'ignoredfiles': u'',
 'localfiletype': 'po',
 'source_language': '/api/v1/languages/2/',
 'translation_projects': [],
 'treestyle': 'auto',
}

api.projects.post(fields)
```

returns a `HttpServerError: Server Error 500: http://localhost:8000/api/v1/projects/`, which upon closer tracing and debugging seems to be caused by the line `tastypie/authorization.py:190`: 

```
        if not bundle.request.user.has_perm(permission):
```

causing an `AttributeError: 'User' object has no attribute 'has_perm'`.  Have I discovered a bug, or am I simply doing something wrong?

If someone could show me some working code examples of how to do this, I would be very happy.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pootle/apps/accounts/models.py`
Content:
```
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # Copyright 2014 Evernote Corporation
5 #
6 # This file is part of Pootle.
7 #
8 # Pootle is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
12 #
13 # Pootle is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with Pootle; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 
22 import re
23 from hashlib import md5
24 
25 from django.contrib.auth.models import AbstractBaseUser
26 from django.core.mail import send_mail
27 from django.core.urlresolvers import reverse
28 from django.core.validators import RegexValidator
29 from django.db import models
30 from django.db.models import Q
31 from django.db.models.signals import post_save
32 from django.dispatch import receiver
33 from django.utils import timezone
34 from django.utils.functional import cached_property
35 from django.utils.translation import ugettext_lazy as _
36 
37 from pootle_app.models import Directory
38 from pootle_autonotices.signals import new_object
39 from pootle_language.models import Language
40 from pootle_statistics.models import Submission, SubmissionTypes
41 from pootle_store.models import SuggestionStates
42 from pootle_translationproject.models import TranslationProject
43 from .managers import UserManager
44 
45 
46 class User(AbstractBaseUser):
47     """The Pootle User.
48 
49     ``username``, ``password`` and ``email`` are required. Other fields
50     are optional.
51 
52     Note that the ``password`` and ``last_login`` fields are inherited
53     from ``AbstractBaseUser``.
54     """
55     username = models.CharField(_("username"), max_length=30, unique=True,
56         help_text=_("Required. 30 characters or fewer. Letters, numbers and "
57                     "@/./+/-/_ characters"),
58         validators=[
59             RegexValidator(re.compile("^[\w.@+-]+$"),
60                            _("Enter a valid username."),
61                            "invalid")
62         ],
63     )
64     email = models.EmailField(_("email address"), max_length=255)
65     full_name = models.CharField(_("Full name"), max_length=255, blank=True)
66 
67     is_active = models.BooleanField(_("active"), default=True,
68         help_text=_("Designates whether this user should be treated as "
69                     "active. Unselect this instead of deleting accounts."))
70     is_superuser = models.BooleanField(_("superuser status"), default=False,
71         help_text=_("Designates that this user has all permissions without "
72                     "explicitly assigning them."))
73 
74     date_joined = models.DateTimeField(_("date joined"), default=timezone.now)
75 
76     # Profile fields
77     _unit_rows = models.SmallIntegerField(_("Number of Rows"), default=9,
78         db_column="unit_rows")
79 
80     alt_src_langs = models.ManyToManyField(
81         "pootle_language.Language",
82         blank=True,
83         db_index=True,
84         limit_choices_to=~Q(code="templates"),
85         related_name="user_alt_src_langs",
86         verbose_name=_("Alternative Source Languages"),
87     )
88 
89     USERNAME_FIELD = "username"
90     REQUIRED_FIELDS = ["email"]
91 
92     objects = UserManager()
93 
94     @property
95     def display_name(self):
96         """Human-readable display name."""
97         return (self.get_full_name() if self.get_full_name()
98                                      else self.get_short_name())
99 
100     @property
101     def is_staff(self):
102         # For compatibility with django admin.
103         return self.is_superuser
104 
105     def __unicode__(self):
106         return self.username
107 
108     def get_absolute_url(self):
109         # FIXME: adapt once we get rid of the profiles app
110         return reverse("profiles_profile_detail", args=[self.username])
111 
112     @cached_property
113     def email_hash(self):
114         try:
115             return md5(self.email).hexdigest()
116         except UnicodeEncodeError:
117             return None
118 
119     @property
120     def contributions(self):
121         """Get user contributions grouped by language and project.
122 
123         :return: List of tuples containing the following information::
124 
125             [
126               ('Language 1', [
127                   ('Project 1', [
128                       {
129                         'id': 'foo-bar',
130                         'count': 0,
131                         'url': 'foo/bar',
132                       },
133                       {
134                         'id': 'bar-foo',
135                         'count': 3,
136                         'url': 'baz/blah',
137                       },
138                       {
139                         'id': 'baz-blah',
140                         'count': 5,
141                         'url': 'bar/baz',
142                       },
143                   ]),
144                   ('Project 2', [
145                       ...
146                   ]),
147               ]),
148               ('LanguageN', [
149                   ('Project N', [
150                       ...
151                   ]),
152                   ('Project N+1', [
153                       ...
154                   ]),
155               ]),
156             ]
157         """
158 
159         def suggestion_count(tp, state):
160             "Return a filtered count of the user's suggestions (internal)"
161             return self.suggestions.filter(translation_project=tp, state=state).count()
162 
163         contributions = []
164         username = self.username
165 
166         languages = Language.objects.filter(
167             translationproject__submission__submitter=self,
168             translationproject__submission__type=SubmissionTypes.NORMAL,
169         ).distinct()
170 
171         for language in languages:
172             translation_projects = TranslationProject.objects.filter(
173                     language=language,
174                     submission__submitter=self,
175                     submission__type=SubmissionTypes.NORMAL,
176                 ).distinct().order_by('project__fullname')
177 
178             tp_user_stats = []
179             # Retrieve tp-specific stats for this user.
180             for tp in translation_projects:
181                 # Submissions from the user done from the editor
182                 total_subs = Submission.objects.filter(
183                     submitter=self,
184                     translation_project=tp,
185                     type=SubmissionTypes.NORMAL,
186                 )
187                 # Submissions from the user done from the editor that have been
188                 # overwritten by other users
189                 overwritten_subs = total_subs.exclude(unit__submitted_by=self)
190 
191                 tp_stats = [
192                     {
193                         'id': 'suggestions-pending',
194                         'count': suggestion_count(tp, SuggestionStates.PENDING),
195                         'url': tp.get_translate_url(state='user-suggestions',
196                                                     user=username),
197                     },
198                     {
199                         'id': 'suggestions-accepted',
200                         'count': suggestion_count(tp, SuggestionStates.ACCEPTED),
201                         'url': tp.get_translate_url(
202                             state='user-suggestions-accepted',
203                             user=username,
204                         ),
205                     },
206                     {
207                         'id': 'suggestions-rejected',
208                         'count': suggestion_count(tp, SuggestionStates.REJECTED),
209                         'url': tp.get_translate_url(
210                             state='user-suggestions-rejected',
211                             user=username,
212                         ),
213                     },
214                     {
215                         'id': 'submissions-total',
216                         'count': total_subs.count(),
217                         'url': tp.get_translate_url(state='user-submissions',
218                                                     user=username),
219                     },
220                     {
221                         'id': 'submissions-overwritten',
222                         'count': overwritten_subs.count(),
223                         'url': tp.get_translate_url(
224                             state='user-submissions-overwritten',
225                             user=username,
226                         ),
227                     },
228                 ]
229 
230                 tp_user_stats.append((tp, tp_stats))
231 
232             contributions.append((language, tp_user_stats))
233 
234         return contributions
235 
236     @property
237     def unit_rows(self):
238         # NOTE: This could be done using MinValueValidator and MaxValueValidator
239         # But that is more complicated than really necessary
240         return min(max(self._unit_rows, 5), 49)
241 
242     def gravatar_url(self, size=80):
243         if not self.email_hash:
244             return ""
245 
246         api_url = "https://secure.gravatar.com/avatar/%(hash)s?s=%(size)d&d=mm"
247         return api_url % {"hash": self.email_hash, "size": size}
248 
249     def get_full_name(self):
250         """Returns the user's full name."""
251         return self.full_name
252 
253     def get_short_name(self):
254         """Returns the short name for the user."""
255         return self.username
256 
257     def email_user(self, subject, message, from_email=None):
258         """Sends an email to this user."""
259         send_mail(subject, message, from_email, [self.email])
260 
261 
262 @receiver(post_save, sender=User)
263 def new_user(sender, instance, created=False, raw=False, **kwargs):
264     if raw:
265         return
266 
267     args = {
268         "url": instance.get_absolute_url(),
269         "user": instance,
270     }
271     message = 'New user <a href="%(url)s">%(user)s</a> registered.' % args
272     new_object(created, message, parent=Directory.objects.root)
273
```
--- 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/pootle/apps/accounts/models.py b/pootle/apps/accounts/models.py
--- a/pootle/apps/accounts/models.py
+++ b/pootle/apps/accounts/models.py
@@ -22,7 +22,7 @@
 import re
 from hashlib import md5
 
-from django.contrib.auth.models import AbstractBaseUser
+from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
 from django.core.mail import send_mail
 from django.core.urlresolvers import reverse
 from django.core.validators import RegexValidator
@@ -43,7 +43,7 @@
 from .managers import UserManager
 
 
-class User(AbstractBaseUser):
+class User(AbstractBaseUser, PermissionsMixin):
     """The Pootle User.
 
     ``username``, ``password`` and ``email`` are required. Other fields
@@ -67,9 +67,6 @@
     is_active = models.BooleanField(_("active"), default=True,
         help_text=_("Designates whether this user should be treated as "
                     "active. Unselect this instead of deleting accounts."))
-    is_superuser = models.BooleanField(_("superuser status"), default=False,
-        help_text=_("Designates that this user has all permissions without "
-                    "explicitly assigning them."))
 
     date_joined = models.DateTimeField(_("date joined"), default=timezone.now)

{"golden_diff": "diff --git a/pootle/apps/accounts/models.py b/pootle/apps/accounts/models.py\n--- a/pootle/apps/accounts/models.py\n+++ b/pootle/apps/accounts/models.py\n@@ -22,7 +22,7 @@\n import re\n from hashlib import md5\n \n-from django.contrib.auth.models import AbstractBaseUser\n+from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin\n from django.core.mail import send_mail\n from django.core.urlresolvers import reverse\n from django.core.validators import RegexValidator\n@@ -43,7 +43,7 @@\n from .managers import UserManager\n \n \n-class User(AbstractBaseUser):\n+class User(AbstractBaseUser, PermissionsMixin):\n     \"\"\"The Pootle User.\n \n     ``username``, ``password`` and ``email`` are required. Other fields\n@@ -67,9 +67,6 @@\n     is_active = models.BooleanField(_(\"active\"), default=True,\n         help_text=_(\"Designates whether this user should be treated as \"\n                     \"active. Unselect this instead of deleting accounts.\"))\n-    is_superuser = models.BooleanField(_(\"superuser status\"), default=False,\n-        help_text=_(\"Designates that this user has all permissions without \"\n-                    \"explicitly assigning them.\"))\n \n     date_joined = models.DateTimeField(_(\"date joined\"), default=timezone.now)\n", "issue": "Is it possible to use the REST API to create and update a Project, with related resources, like Store, Translation Project, and Unit? \nI have spent considerable time now, trying to create a simple Project instance, using the REST API, but with no success so far.\n\nInstalled packages (pip freeze, with Python version 2.7.6):\n\n```\nDjango==1.6.7\nPootle==2.6.0-rc2\nSouth==1.0\nargparse==1.2.1\ncssmin==0.2.0\ndiff-match-patch==20121119\ndjango-allauth==0.16.1\ndjango-assets==0.10\ndjango-contact-form==1.0\ndjango-taggit==0.11.1\ndjango-tastypie==0.12.0\ndjango-voting==0.1\nlxml==3.4.0\noauthlib==0.6.3\npython-dateutil==2.2\npython-memcached==1.53\npython-mimeparse==0.1.4\npython-openid==2.2.5\nrequests==2.4.3\nrequests-oauthlib==0.4.1\nsix==1.8.0\n```\n\nI use the the slumber library to access the API.  The following code\n\n``` python\napi = slumber.API('http://localhost:8000/api/v1/', auth=('admin', 'admin'))\napi.projects.get()\n```\n\nreturns the expected \n\n```\n{'meta': {'limit': 1000,\n  'next': None,\n  'offset': 0,\n  'previous': None,\n  'total_count': 2},\n 'objects': [{'backlink': 'http://localhost:8000/projects/terminology/',\n   'checkstyle': 'terminology',\n   'code': 'terminology',\n   'description': u'',\n   'fullname': 'Terminology',\n   'ignoredfiles': u'',\n   'localfiletype': 'po',\n   'resource_uri': '/api/v1/projects/1/',\n   'source_language': '/api/v1/languages/2/',\n   'translation_projects': ['/api/v1/translation-projects/2/',\n    '/api/v1/translation-projects/3/',\n    # [\u2026]\n    '/api/v1/translation-projects/62/',\n    '/api/v1/translation-projects/63/'],\n   'treestyle': 'auto'},\n  {'backlink': 'http://localhost:8000/projects/tutorial/',\n   'checkstyle': 'standard',\n   'code': 'tutorial',\n   'description': '<div dir=\"ltr\" lang=\"en\">Tutorial project where users can play with Pootle and learn more about translation and localisation.<br>For more help on localisation, visit the <a href=\"http://docs.translatehouse.org/projects/localization-guide/en/latest/guide/start.html\">localisation guide</a>.</div>',\n   'fullname': 'Tutorial',\n   'ignoredfiles': u'',\n   'localfiletype': 'po',\n   'resource_uri': '/api/v1/projects/2/',\n   'source_language': '/api/v1/languages/2/',\n   'translation_projects': ['/api/v1/translation-projects/1/',\n    '/api/v1/translation-projects/28/',\n    '/api/v1/translation-projects/33/',\n    '/api/v1/translation-projects/35/',\n    '/api/v1/translation-projects/37/',\n    '/api/v1/translation-projects/46/'],\n   'treestyle': 'auto'}]}\n```\n\nWhile attempting the following code: \n\n``` python\nfields = {\n 'checkstyle': 'standard',\n 'code': 'test01',\n 'description': 'Another test.',\n 'fullname': 'Test #01',\n 'ignoredfiles': u'',\n 'localfiletype': 'po',\n 'source_language': '/api/v1/languages/2/',\n 'translation_projects': [],\n 'treestyle': 'auto',\n}\n\napi.projects.post(fields)\n```\n\nreturns a `HttpServerError: Server Error 500: http://localhost:8000/api/v1/projects/`, which upon closer tracing and debugging seems to be caused by the line `tastypie/authorization.py:190`: \n\n```\n        if not bundle.request.user.has_perm(permission):\n```\n\ncausing an `AttributeError: 'User' object has no attribute 'has_perm'`.  Have I discovered a bug, or am I simply doing something wrong?\n\nIf someone could show me some working code examples of how to do this, I would be very happy.\n\n", "before_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n#\n# Copyright 2014 Evernote Corporation\n#\n# This file is part of Pootle.\n#\n# Pootle is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# Pootle is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Pootle; if not, write to the Free Software\n# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nimport re\nfrom hashlib import md5\n\nfrom django.contrib.auth.models import AbstractBaseUser\nfrom django.core.mail import send_mail\nfrom django.core.urlresolvers import reverse\nfrom django.core.validators import RegexValidator\nfrom django.db import models\nfrom django.db.models import Q\nfrom django.db.models.signals import post_save\nfrom django.dispatch import receiver\nfrom django.utils import timezone\nfrom django.utils.functional import cached_property\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom pootle_app.models import Directory\nfrom pootle_autonotices.signals import new_object\nfrom pootle_language.models import Language\nfrom pootle_statistics.models import Submission, SubmissionTypes\nfrom pootle_store.models import SuggestionStates\nfrom pootle_translationproject.models import TranslationProject\nfrom .managers import UserManager\n\n\nclass User(AbstractBaseUser):\n    \"\"\"The Pootle User.\n\n    ``username``, ``password`` and ``email`` are required. Other fields\n    are optional.\n\n    Note that the ``password`` and ``last_login`` fields are inherited\n    from ``AbstractBaseUser``.\n    \"\"\"\n    username = models.CharField(_(\"username\"), max_length=30, unique=True,\n        help_text=_(\"Required. 30 characters or fewer. Letters, numbers and \"\n                    \"@/./+/-/_ characters\"),\n        validators=[\n            RegexValidator(re.compile(\"^[\\w.@+-]+$\"),\n                           _(\"Enter a valid username.\"),\n                           \"invalid\")\n        ],\n    )\n    email = models.EmailField(_(\"email address\"), max_length=255)\n    full_name = models.CharField(_(\"Full name\"), max_length=255, blank=True)\n\n    is_active = models.BooleanField(_(\"active\"), default=True,\n        help_text=_(\"Designates whether this user should be treated as \"\n                    \"active. Unselect this instead of deleting accounts.\"))\n    is_superuser = models.BooleanField(_(\"superuser status\"), default=False,\n        help_text=_(\"Designates that this user has all permissions without \"\n                    \"explicitly assigning them.\"))\n\n    date_joined = models.DateTimeField(_(\"date joined\"), default=timezone.now)\n\n    # Profile fields\n    _unit_rows = models.SmallIntegerField(_(\"Number of Rows\"), default=9,\n        db_column=\"unit_rows\")\n\n    alt_src_langs = models.ManyToManyField(\n        \"pootle_language.Language\",\n        blank=True,\n        db_index=True,\n        limit_choices_to=~Q(code=\"templates\"),\n        related_name=\"user_alt_src_langs\",\n        verbose_name=_(\"Alternative Source Languages\"),\n    )\n\n    USERNAME_FIELD = \"username\"\n    REQUIRED_FIELDS = [\"email\"]\n\n    objects = UserManager()\n\n    @property\n    def display_name(self):\n        \"\"\"Human-readable display name.\"\"\"\n        return (self.get_full_name() if self.get_full_name()\n                                     else self.get_short_name())\n\n    @property\n    def is_staff(self):\n        # For compatibility with django admin.\n        return self.is_superuser\n\n    def __unicode__(self):\n        return self.username\n\n    def get_absolute_url(self):\n        # FIXME: adapt once we get rid of the profiles app\n        return reverse(\"profiles_profile_detail\", args=[self.username])\n\n    @cached_property\n    def email_hash(self):\n        try:\n            return md5(self.email).hexdigest()\n        except UnicodeEncodeError:\n            return None\n\n    @property\n    def contributions(self):\n        \"\"\"Get user contributions grouped by language and project.\n\n        :return: List of tuples containing the following information::\n\n            [\n              ('Language 1', [\n                  ('Project 1', [\n                      {\n                        'id': 'foo-bar',\n                        'count': 0,\n                        'url': 'foo/bar',\n                      },\n                      {\n                        'id': 'bar-foo',\n                        'count': 3,\n                        'url': 'baz/blah',\n                      },\n                      {\n                        'id': 'baz-blah',\n                        'count': 5,\n                        'url': 'bar/baz',\n                      },\n                  ]),\n                  ('Project 2', [\n                      ...\n                  ]),\n              ]),\n              ('LanguageN', [\n                  ('Project N', [\n                      ...\n                  ]),\n                  ('Project N+1', [\n                      ...\n                  ]),\n              ]),\n            ]\n        \"\"\"\n\n        def suggestion_count(tp, state):\n            \"Return a filtered count of the user's suggestions (internal)\"\n            return self.suggestions.filter(translation_project=tp, state=state).count()\n\n        contributions = []\n        username = self.username\n\n        languages = Language.objects.filter(\n            translationproject__submission__submitter=self,\n            translationproject__submission__type=SubmissionTypes.NORMAL,\n        ).distinct()\n\n        for language in languages:\n            translation_projects = TranslationProject.objects.filter(\n                    language=language,\n                    submission__submitter=self,\n                    submission__type=SubmissionTypes.NORMAL,\n                ).distinct().order_by('project__fullname')\n\n            tp_user_stats = []\n            # Retrieve tp-specific stats for this user.\n            for tp in translation_projects:\n                # Submissions from the user done from the editor\n                total_subs = Submission.objects.filter(\n                    submitter=self,\n                    translation_project=tp,\n                    type=SubmissionTypes.NORMAL,\n                )\n                # Submissions from the user done from the editor that have been\n                # overwritten by other users\n                overwritten_subs = total_subs.exclude(unit__submitted_by=self)\n\n                tp_stats = [\n                    {\n                        'id': 'suggestions-pending',\n                        'count': suggestion_count(tp, SuggestionStates.PENDING),\n                        'url': tp.get_translate_url(state='user-suggestions',\n                                                    user=username),\n                    },\n                    {\n                        'id': 'suggestions-accepted',\n                        'count': suggestion_count(tp, SuggestionStates.ACCEPTED),\n                        'url': tp.get_translate_url(\n                            state='user-suggestions-accepted',\n                            user=username,\n                        ),\n                    },\n                    {\n                        'id': 'suggestions-rejected',\n                        'count': suggestion_count(tp, SuggestionStates.REJECTED),\n                        'url': tp.get_translate_url(\n                            state='user-suggestions-rejected',\n                            user=username,\n                        ),\n                    },\n                    {\n                        'id': 'submissions-total',\n                        'count': total_subs.count(),\n                        'url': tp.get_translate_url(state='user-submissions',\n                                                    user=username),\n                    },\n                    {\n                        'id': 'submissions-overwritten',\n                        'count': overwritten_subs.count(),\n                        'url': tp.get_translate_url(\n                            state='user-submissions-overwritten',\n                            user=username,\n                        ),\n                    },\n                ]\n\n                tp_user_stats.append((tp, tp_stats))\n\n            contributions.append((language, tp_user_stats))\n\n        return contributions\n\n    @property\n    def unit_rows(self):\n        # NOTE: This could be done using MinValueValidator and MaxValueValidator\n        # But that is more complicated than really necessary\n        return min(max(self._unit_rows, 5), 49)\n\n    def gravatar_url(self, size=80):\n        if not self.email_hash:\n            return \"\"\n\n        api_url = \"https://secure.gravatar.com/avatar/%(hash)s?s=%(size)d&d=mm\"\n        return api_url % {\"hash\": self.email_hash, \"size\": size}\n\n    def get_full_name(self):\n        \"\"\"Returns the user's full name.\"\"\"\n        return self.full_name\n\n    def get_short_name(self):\n        \"\"\"Returns the short name for the user.\"\"\"\n        return self.username\n\n    def email_user(self, subject, message, from_email=None):\n        \"\"\"Sends an email to this user.\"\"\"\n        send_mail(subject, message, from_email, [self.email])\n\n\n@receiver(post_save, sender=User)\ndef new_user(sender, instance, created=False, raw=False, **kwargs):\n    if raw:\n        return\n\n    args = {\n        \"url\": instance.get_absolute_url(),\n        \"user\": instance,\n    }\n    message = 'New user <a href=\"%(url)s\">%(user)s</a> registered.' % args\n    new_object(created, message, parent=Directory.objects.root)\n", "path": "pootle/apps/accounts/models.py"}], "after_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n#\n# Copyright 2014 Evernote Corporation\n#\n# This file is part of Pootle.\n#\n# Pootle is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# Pootle is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Pootle; if not, write to the Free Software\n# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nimport re\nfrom hashlib import md5\n\nfrom django.contrib.auth.models import AbstractBaseUser, PermissionsMixin\nfrom django.core.mail import send_mail\nfrom django.core.urlresolvers import reverse\nfrom django.core.validators import RegexValidator\nfrom django.db import models\nfrom django.db.models import Q\nfrom django.db.models.signals import post_save\nfrom django.dispatch import receiver\nfrom django.utils import timezone\nfrom django.utils.functional import cached_property\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom pootle_app.models import Directory\nfrom pootle_autonotices.signals import new_object\nfrom pootle_language.models import Language\nfrom pootle_statistics.models import Submission, SubmissionTypes\nfrom pootle_store.models import SuggestionStates\nfrom pootle_translationproject.models import TranslationProject\nfrom .managers import UserManager\n\n\nclass User(AbstractBaseUser, PermissionsMixin):\n    \"\"\"The Pootle User.\n\n    ``username``, ``password`` and ``email`` are required. Other fields\n    are optional.\n\n    Note that the ``password`` and ``last_login`` fields are inherited\n    from ``AbstractBaseUser``.\n    \"\"\"\n    username = models.CharField(_(\"username\"), max_length=30, unique=True,\n        help_text=_(\"Required. 30 characters or fewer. Letters, numbers and \"\n                    \"@/./+/-/_ characters\"),\n        validators=[\n            RegexValidator(re.compile(\"^[\\w.@+-]+$\"),\n                           _(\"Enter a valid username.\"),\n                           \"invalid\")\n        ],\n    )\n    email = models.EmailField(_(\"email address\"), max_length=255)\n    full_name = models.CharField(_(\"Full name\"), max_length=255, blank=True)\n\n    is_active = models.BooleanField(_(\"active\"), default=True,\n        help_text=_(\"Designates whether this user should be treated as \"\n                    \"active. Unselect this instead of deleting accounts.\"))\n\n    date_joined = models.DateTimeField(_(\"date joined\"), default=timezone.now)\n\n    # Profile fields\n    _unit_rows = models.SmallIntegerField(_(\"Number of Rows\"), default=9,\n        db_column=\"unit_rows\")\n\n    alt_src_langs = models.ManyToManyField(\n        \"pootle_language.Language\",\n        blank=True,\n        db_index=True,\n        limit_choices_to=~Q(code=\"templates\"),\n        related_name=\"user_alt_src_langs\",\n        verbose_name=_(\"Alternative Source Languages\"),\n    )\n\n    USERNAME_FIELD = \"username\"\n    REQUIRED_FIELDS = [\"email\"]\n\n    objects = UserManager()\n\n    @property\n    def display_name(self):\n        \"\"\"Human-readable display name.\"\"\"\n        return (self.get_full_name() if self.get_full_name()\n                                     else self.get_short_name())\n\n    @property\n    def is_staff(self):\n        # For compatibility with django admin.\n        return self.is_superuser\n\n    def __unicode__(self):\n        return self.username\n\n    def get_absolute_url(self):\n        # FIXME: adapt once we get rid of the profiles app\n        return reverse(\"profiles_profile_detail\", args=[self.username])\n\n    @cached_property\n    def email_hash(self):\n        try:\n            return md5(self.email).hexdigest()\n        except UnicodeEncodeError:\n            return None\n\n    @property\n    def contributions(self):\n        \"\"\"Get user contributions grouped by language and project.\n\n        :return: List of tuples containing the following information::\n\n            [\n              ('Language 1', [\n                  ('Project 1', [\n                      {\n                        'id': 'foo-bar',\n                        'count': 0,\n                        'url': 'foo/bar',\n                      },\n                      {\n                        'id': 'bar-foo',\n                        'count': 3,\n                        'url': 'baz/blah',\n                      },\n                      {\n                        'id': 'baz-blah',\n                        'count': 5,\n                        'url': 'bar/baz',\n                      },\n                  ]),\n                  ('Project 2', [\n                      ...\n                  ]),\n              ]),\n              ('LanguageN', [\n                  ('Project N', [\n                      ...\n                  ]),\n                  ('Project N+1', [\n                      ...\n                  ]),\n              ]),\n            ]\n        \"\"\"\n\n        def suggestion_count(tp, state):\n            \"Return a filtered count of the user's suggestions (internal)\"\n            return self.suggestions.filter(translation_project=tp, state=state).count()\n\n        contributions = []\n        username = self.username\n\n        languages = Language.objects.filter(\n            translationproject__submission__submitter=self,\n            translationproject__submission__type=SubmissionTypes.NORMAL,\n        ).distinct()\n\n        for language in languages:\n            translation_projects = TranslationProject.objects.filter(\n                    language=language,\n                    submission__submitter=self,\n                    submission__type=SubmissionTypes.NORMAL,\n                ).distinct().order_by('project__fullname')\n\n            tp_user_stats = []\n            # Retrieve tp-specific stats for this user.\n            for tp in translation_projects:\n                # Submissions from the user done from the editor\n                total_subs = Submission.objects.filter(\n                    submitter=self,\n                    translation_project=tp,\n                    type=SubmissionTypes.NORMAL,\n                )\n                # Submissions from the user done from the editor that have been\n                # overwritten by other users\n                overwritten_subs = total_subs.exclude(unit__submitted_by=self)\n\n                tp_stats = [\n                    {\n                        'id': 'suggestions-pending',\n                        'count': suggestion_count(tp, SuggestionStates.PENDING),\n                        'url': tp.get_translate_url(state='user-suggestions',\n                                                    user=username),\n                    },\n                    {\n                        'id': 'suggestions-accepted',\n                        'count': suggestion_count(tp, SuggestionStates.ACCEPTED),\n                        'url': tp.get_translate_url(\n                            state='user-suggestions-accepted',\n                            user=username,\n                        ),\n                    },\n                    {\n                        'id': 'suggestions-rejected',\n                        'count': suggestion_count(tp, SuggestionStates.REJECTED),\n                        'url': tp.get_translate_url(\n                            state='user-suggestions-rejected',\n                            user=username,\n                        ),\n                    },\n                    {\n                        'id': 'submissions-total',\n                        'count': total_subs.count(),\n                        'url': tp.get_translate_url(state='user-submissions',\n                                                    user=username),\n                    },\n                    {\n                        'id': 'submissions-overwritten',\n                        'count': overwritten_subs.count(),\n                        'url': tp.get_translate_url(\n                            state='user-submissions-overwritten',\n                            user=username,\n                        ),\n                    },\n                ]\n\n                tp_user_stats.append((tp, tp_stats))\n\n            contributions.append((language, tp_user_stats))\n\n        return contributions\n\n    @property\n    def unit_rows(self):\n        # NOTE: This could be done using MinValueValidator and MaxValueValidator\n        # But that is more complicated than really necessary\n        return min(max(self._unit_rows, 5), 49)\n\n    def gravatar_url(self, size=80):\n        if not self.email_hash:\n            return \"\"\n\n        api_url = \"https://secure.gravatar.com/avatar/%(hash)s?s=%(size)d&d=mm\"\n        return api_url % {\"hash\": self.email_hash, \"size\": size}\n\n    def get_full_name(self):\n        \"\"\"Returns the user's full name.\"\"\"\n        return self.full_name\n\n    def get_short_name(self):\n        \"\"\"Returns the short name for the user.\"\"\"\n        return self.username\n\n    def email_user(self, subject, message, from_email=None):\n        \"\"\"Sends an email to this user.\"\"\"\n        send_mail(subject, message, from_email, [self.email])\n\n\n@receiver(post_save, sender=User)\ndef new_user(sender, instance, created=False, raw=False, **kwargs):\n    if raw:\n        return\n\n    args = {\n        \"url\": instance.get_absolute_url(),\n        \"user\": instance,\n    }\n    message = 'New user <a href=\"%(url)s\">%(user)s</a> registered.' % args\n    new_object(created, message, parent=Directory.objects.root)\n", "path": "pootle/apps/accounts/models.py"}]}