Commits

Matthew Schinckel  committed 8285a8f Merge

Merge

  • Participants
  • Parent commits 9cb2118, e01d94e

Comments (0)

Files changed (6)

File auth_additions/admin.py

File contents unchanged.

File auth_additions/backends.py

+from django.db.models.fields.related import SingleRelatedObjectDescriptor
 from django.contrib.auth.models import User
 
+USER_SUBCLASSES = [o for o in dir(User)
+                     if isinstance(getattr(User, o), SingleRelatedObjectDescriptor)
+                     and issubclass(getattr(User, o).related.model, User)]
+
 class EmailBackend(object):
     supports_object_permissions = False
     supports_anonymous_user = False
         if '@' in username:
             for user in User.objects.filter(email=username, is_active=True):
                 if user.check_password(password):
-                    return user
+                    return self.get_user(user.pk)
         return None
     
     def get_user(self, user_id):
         try:
-            return User.objects.get(pk=user_id)
+            user = User.objects.select_related(*USER_SUBCLASSES).get(pk=user_id)
+            return ([getattr(user, s) for s in USER_SUBCLASSES if getattr(user, s)] or [user])[0]
         except User.DoesNotExist:
             return None
 

File auth_additions/forms.py

             'invalid': _("This value may contain only letters, numbers and "
                          "@/ /./+/-/_ characters.")}
     )
+
+class UserEmailUniqueMixin(object):
+    """
+    Mixin this class if you require all email addresses (across all
+    sub-classes of User) to be unique.
+    """
+    def clean_email(self):
+        email = self.cleaned_data['email']
+        if User.objects.exclude(pk=self.instance.pk).filter(email=email, is_active=True).exists():
+            raise forms.ValidationError("That email address is in use.")
+        return email

File auth_additions/migrations/0002_increase_column_lengths.py

     def forwards(self, orm):
         db.alter_column('auth_user', 'first_name', models.CharField(max_length=128))
         db.alter_column('auth_user', 'last_name', models.CharField(max_length=128))
-        db.alter_column('auth_user', 'username', models.CharField(max_length=128, blank=False))
-        db.alter_column('auth_user', 'email', models.EmailField(max_length=128))
+        db.alter_column('auth_user', 'username', models.CharField(max_length=128, null=True))
+        db.alter_column('auth_user', 'email', models.EmailField(max_length=128, blank=False, null=True))
 
     def backwards(self, orm):
         pass

File auth_additions/models.py

 from functools import wraps
 
+from django.core.exceptions import ValidationError
+from django.dispatch import receiver
+from django.utils.translation import ugettext_lazy as _
 from django.db import models
 from django.contrib.auth.models import User, Group, Permission
 from django.core.validators import MaxLengthValidator
     field = User._meta.get_field_by_name(f_name)[0]
     increase_field_length(field, 128)
 
+# Make email address unique
+field = User._meta.get_field_by_name('email')[0]
+field._unique = True
+field.default = None
+field.null = True
+
+@receiver(models.signals.pre_save, sender=User)
+def User_pre_save(sender, instance, **kwargs):
+    """
+    Ensure that email is unique.
+    """
+    if sender.objects.filter(email=instance.email).exclude(pk=instance.pk).exclude(email=None).exists():
+        raise ValidationError(_("Email must be unique"))
+
+field = User._meta.get_field_by_name('username')[0]
+field.default = None
+field.null = True
+
+# Change the default represention of a User to contain fullname, and email/username.
+
+def User__unicode(self):
+    return "%s %s <%s>" % (self.first_name, self.last_name, self.email or self.username)
+User.__unicode__ = User__unicodefrom functools import wraps
+
 
 # Add a queryset method that will allow for
 #
 #       User.objects.with_permissions('foo.bar')
 #
+
 class PermissionFilterMixin:
     def with_permissions(self, *permission_names):
         """

File auth_additions/queryset.py

+from django.db.models.fields.related import SingleRelatedObjectDescriptor
+from django.db.models.query import QuerySet
+
+class InheritanceQuerySet(QuerySet):
+    def select_subclasses(self, *subclasses):
+        if not subclasses:
+            subclasses = [o for o in dir(self.model)
+                          if isinstance(getattr(self.model, o), SingleRelatedObjectDescriptor)\
+                          and issubclass(getattr(self.model,o).related.model, self.model)]
+        new_qs = self.select_related(*subclasses)
+        new_qs.subclasses = subclasses
+        return new_qs
+
+    def _clone(self, klass=None, setup=False, **kwargs):
+        try:
+            kwargs.update({'subclasses': self.subclasses})
+        except AttributeError:
+            pass
+        return super(InheritanceQuerySet, self)._clone(klass, setup, **kwargs)
+
+    def iterator(self):
+        iter = super(InheritanceQuerySet, self).iterator()
+        if getattr(self, 'subclasses', False):
+            for obj in iter:
+                obj = [getattr(obj, s) for s in self.subclasses if getattr(obj, s)] or [obj]
+                yield obj[0]
+        else:
+            for obj in iter:
+                yield obj