Fixed #13914 -- Added natural keys to User and Group models in auth contrib app. Thanks, jbochi and closedbracket.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17429 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
6ecadcbdd2
commit
954e3b4ad3
|
@ -0,0 +1,32 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"pk": 1,
|
||||||
|
"model": "auth.group",
|
||||||
|
"fields": {
|
||||||
|
"name": "my_group",
|
||||||
|
"permissions": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pk": 1,
|
||||||
|
"model": "auth.user",
|
||||||
|
"fields": {
|
||||||
|
"username": "my_username",
|
||||||
|
"first_name": "",
|
||||||
|
"last_name": "",
|
||||||
|
"is_active": true,
|
||||||
|
"is_superuser": true,
|
||||||
|
"is_staff": true,
|
||||||
|
"last_login": "2012-01-13 00:14:00",
|
||||||
|
"groups": [
|
||||||
|
[
|
||||||
|
"my_group"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"user_permissions": [],
|
||||||
|
"password": "pbkdf2_sha256$10000$LUyhxJjuLwXF$f6Zbpnx1L5dPze8m0itBaHMDyZ/n6JyhuavQy2RrBIM=",
|
||||||
|
"email": "email@example.com",
|
||||||
|
"date_joined": "2012-01-13 00:14:00"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,30 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"pk": 1,
|
||||||
|
"model": "auth.group",
|
||||||
|
"fields": {
|
||||||
|
"name": "my_group",
|
||||||
|
"permissions": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pk": 1,
|
||||||
|
"model": "auth.user",
|
||||||
|
"fields": {
|
||||||
|
"username": "my_username",
|
||||||
|
"first_name": "",
|
||||||
|
"last_name": "",
|
||||||
|
"is_active": true,
|
||||||
|
"is_superuser": true,
|
||||||
|
"is_staff": true,
|
||||||
|
"last_login": "2012-01-13 00:14:00",
|
||||||
|
"groups": [
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"user_permissions": [],
|
||||||
|
"password": "pbkdf2_sha256$10000$LUyhxJjuLwXF$f6Zbpnx1L5dPze8m0itBaHMDyZ/n6JyhuavQy2RrBIM=",
|
||||||
|
"email": "email@example.com",
|
||||||
|
"date_joined": "2012-01-13 00:14:00"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
|
@ -86,6 +86,13 @@ class Permission(models.Model):
|
||||||
natural_key.dependencies = ['contenttypes.contenttype']
|
natural_key.dependencies = ['contenttypes.contenttype']
|
||||||
|
|
||||||
|
|
||||||
|
class GroupManager(models.Manager):
|
||||||
|
"""
|
||||||
|
The manager for the auth's Group model.
|
||||||
|
"""
|
||||||
|
def get_by_natural_key(self, name):
|
||||||
|
return self.get(name=name)
|
||||||
|
|
||||||
class Group(models.Model):
|
class Group(models.Model):
|
||||||
"""
|
"""
|
||||||
Groups are a generic way of categorizing users to apply permissions, or
|
Groups are a generic way of categorizing users to apply permissions, or
|
||||||
|
@ -107,6 +114,8 @@ class Group(models.Model):
|
||||||
permissions = models.ManyToManyField(Permission,
|
permissions = models.ManyToManyField(Permission,
|
||||||
verbose_name=_('permissions'), blank=True)
|
verbose_name=_('permissions'), blank=True)
|
||||||
|
|
||||||
|
objects = GroupManager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('group')
|
verbose_name = _('group')
|
||||||
verbose_name_plural = _('groups')
|
verbose_name_plural = _('groups')
|
||||||
|
@ -114,6 +123,9 @@ class Group(models.Model):
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def natural_key(self):
|
||||||
|
return (self.name,)
|
||||||
|
|
||||||
|
|
||||||
class UserManager(models.Manager):
|
class UserManager(models.Manager):
|
||||||
def create_user(self, username, email=None, password=None):
|
def create_user(self, username, email=None, password=None):
|
||||||
|
@ -160,6 +172,9 @@ class UserManager(models.Manager):
|
||||||
"""
|
"""
|
||||||
return get_random_string(length, allowed_chars)
|
return get_random_string(length, allowed_chars)
|
||||||
|
|
||||||
|
def get_by_natural_key(self, username):
|
||||||
|
return self.get(username=username)
|
||||||
|
|
||||||
|
|
||||||
# A few helper functions for common logic between User and AnonymousUser.
|
# A few helper functions for common logic between User and AnonymousUser.
|
||||||
def _user_get_all_permissions(user, obj):
|
def _user_get_all_permissions(user, obj):
|
||||||
|
@ -240,6 +255,9 @@ class User(models.Model):
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.username
|
return self.username
|
||||||
|
|
||||||
|
def natural_key(self):
|
||||||
|
return (self.username,)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return "/users/%s/" % urllib.quote(smart_str(self.username))
|
return "/users/%s/" % urllib.quote(smart_str(self.username))
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,8 @@ from django.contrib.auth.tests.forms import (UserCreationFormTest,
|
||||||
from django.contrib.auth.tests.remote_user import (RemoteUserTest,
|
from django.contrib.auth.tests.remote_user import (RemoteUserTest,
|
||||||
RemoteUserNoCreateTest, RemoteUserCustomTest)
|
RemoteUserNoCreateTest, RemoteUserCustomTest)
|
||||||
from django.contrib.auth.tests.management import GetDefaultUsernameTestCase
|
from django.contrib.auth.tests.management import GetDefaultUsernameTestCase
|
||||||
from django.contrib.auth.tests.models import ProfileTestCase
|
from django.contrib.auth.tests.models import (ProfileTestCase, NaturalKeysTestCase,
|
||||||
|
LoadDataWithoutNaturalKeysTestCase, LoadDataWithNaturalKeysTestCase)
|
||||||
from django.contrib.auth.tests.hashers import TestUtilsHashPass
|
from django.contrib.auth.tests.hashers import TestUtilsHashPass
|
||||||
from django.contrib.auth.tests.signals import SignalTestCase
|
from django.contrib.auth.tests.signals import SignalTestCase
|
||||||
from django.contrib.auth.tests.tokens import TokenGeneratorTest
|
from django.contrib.auth.tests.tokens import TokenGeneratorTest
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.contrib.auth.models import User, SiteProfileNotAvailable
|
from django.contrib.auth.models import Group, User, SiteProfileNotAvailable
|
||||||
|
|
||||||
class ProfileTestCase(TestCase):
|
class ProfileTestCase(TestCase):
|
||||||
fixtures = ['authtestdata.json']
|
fixtures = ['authtestdata.json']
|
||||||
|
@ -33,3 +33,34 @@ class ProfileTestCase(TestCase):
|
||||||
# module that doesn't exist
|
# module that doesn't exist
|
||||||
settings.AUTH_PROFILE_MODULE = 'foo.bar'
|
settings.AUTH_PROFILE_MODULE = 'foo.bar'
|
||||||
self.assertRaises(SiteProfileNotAvailable, user.get_profile)
|
self.assertRaises(SiteProfileNotAvailable, user.get_profile)
|
||||||
|
|
||||||
|
|
||||||
|
class NaturalKeysTestCase(TestCase):
|
||||||
|
fixtures = ['authtestdata.json']
|
||||||
|
|
||||||
|
def test_user_natural_key(self):
|
||||||
|
staff_user = User.objects.get(username='staff')
|
||||||
|
self.assertEquals(User.objects.get_by_natural_key('staff'), staff_user)
|
||||||
|
self.assertEquals(staff_user.natural_key(), ('staff',))
|
||||||
|
|
||||||
|
def test_group_natural_key(self):
|
||||||
|
users_group = Group.objects.create(name='users')
|
||||||
|
self.assertEquals(Group.objects.get_by_natural_key('users'), users_group)
|
||||||
|
|
||||||
|
|
||||||
|
class LoadDataWithoutNaturalKeysTestCase(TestCase):
|
||||||
|
fixtures = ['regular.json']
|
||||||
|
|
||||||
|
def test_user_is_created_and_added_to_group(self):
|
||||||
|
user = User.objects.get(username='my_username')
|
||||||
|
group = Group.objects.get(name='my_group')
|
||||||
|
self.assertEquals(group, user.groups.get())
|
||||||
|
|
||||||
|
|
||||||
|
class LoadDataWithNaturalKeysTestCase(TestCase):
|
||||||
|
fixtures = ['natural.json']
|
||||||
|
def test_user_is_created_and_added_to_group(self):
|
||||||
|
user = User.objects.get(username='my_username')
|
||||||
|
group = Group.objects.get(name='my_group')
|
||||||
|
self.assertEquals(group, user.groups.get())
|
||||||
|
|
||||||
|
|
|
@ -215,7 +215,9 @@ automatically created by Django during the database synchronization process,
|
||||||
the primary key of a given content type isn't easy to predict; it will
|
the primary key of a given content type isn't easy to predict; it will
|
||||||
depend on how and when :djadmin:`syncdb` was executed. This is true for all
|
depend on how and when :djadmin:`syncdb` was executed. This is true for all
|
||||||
models which automatically generate objects, notably including
|
models which automatically generate objects, notably including
|
||||||
:class:`~django.contrib.auth.models.Permission`.
|
:class:`~django.contrib.auth.models.Permission`,
|
||||||
|
:class:`~django.contrib.auth.models.Group`, and
|
||||||
|
:class:`~django.contrib.auth.models.User`.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue