Reputation: 601
I'm experiencing a problem with Django users and the Django REST Framework.
In my settings I have defined a custom user model:
AUTH_USER_MODEL = 'api.User'
In my sandbox.api package I have defined this model in the models.py file:
from django.db import models
from django.core.exceptions import ValidationError
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import UserManager
from django.contrib.auth.models import PermissionsMixin
from django.utils.translation import ugettext_lazy as _
from django.core import validators
from django.core.mail import send_mail
from django.utils import timezone
from django.core.exceptions import NON_FIELD_ERRORS
from random import randrange
class User(AbstractBaseUser, PermissionsMixin):
"""
Custom user class
"""
username = models.CharField(_('username'), max_length=20, unique=True,
help_text=_('Required. 30 characters or fewer. Letters and digits only.'),
validators=[
validators.RegexValidator(r'^[a-z0-9A-Z]{1,20}$', _('Enter a valid username.'), 'invalid')
])
email = models.EmailField(_('email address'), max_length=60, blank=False, null=False, unique=True)
is_staff = models.BooleanField(_('staff status'), default=False,
help_text=_('Designates whether the user can log into this admin '
'site.'))
is_active = models.BooleanField(_('active'), default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
def get_full_name(self):
return self.username
def get_short_name(self):
return self.username
def email_user(self, subject, message, from_email=None, **kwargs):
send_mail(subject, message, from_email, [self.email], **kwargs)
def clean(self):
errors = {}
id = self.id
if not id:
id = 0
n = len(list(User.objects.raw('SELECT id FROM auth_user WHERE LOWER(username) = LOWER(%s) AND id != %s', [self.username, id])))
if n > 0:
errors['username'] = 'User with this username already exists.'
n = len(list(User.objects.raw('SELECT id FROM auth_user WHERE LOWER(email) = LOWER(%s) AND id != %s', [self.email, id])))
if n > 0:
errors['email'] = 'User with this e-mail address already exists.'
if len(errors) > 0:
raise ValidationError(errors)
def save(self, *args, **kwargs):
self.username = self.username.lower()
self.email = self.email.lower()
super(User, self).save(*args, **kwargs)
def __unicode__(self):
return u'%s' % self.username
class Meta:
db_table = 'auth_user'
verbose_name = _('user')
verbose_name_plural = _('users')
abstract = False
And in my sandbox.api package I have defined a serializer in the serializers.py file:
class UserSerializer(ExtSerializer):
"""
User serializer
"""
name = serializers.SerializerMethodField('get_name')
description = serializers.SerializerMethodField('get_description')
url = serializers.SerializerMethodField('get_url')
location = serializers.SerializerMethodField('get_location')
facebook_id = serializers.SerializerMethodField('get_facebook_id')
twitter_id = serializers.SerializerMethodField('get_twitter_id')
path = serializers.SerializerMethodField('get_path')
feed = serializers.HyperlinkedIdentityField(lookup_field='username', view_name='user-feed-collection')
timeline = serializers.HyperlinkedIdentityField(lookup_field='username', view_name='user-timeline-collection')
followers = serializers.HyperlinkedIdentityField(lookup_field='username', view_name='user-follower-collection')
following = serializers.HyperlinkedIdentityField(lookup_field='username', view_name='user-following-collection')
posts_count = serializers.SerializerMethodField('get_posts_count')
followers_count = serializers.SerializerMethodField('get_followers_count')
following_count = serializers.SerializerMethodField('get_following_count')
def get_path(self, user):
request = self.context['view'].request
return reverse_lazy('user-singleton', kwargs={
"username": user.username
}, request=request, format=FORMAT_SUFFIX)
def get_facebook_id(self, user):
return user.profile.facebook_id
def get_twitter_id(self, user):
return user.profile.twitter_id
def get_posts_count(self, user):
return Post.objects.filter(author__pk=user.pk).count()
def get_following_count(self, user):
return Follower.objects.filter(follower=user.pk).count()
def get_followers_count(self, user):
return Follower.objects.filter(following=user.pk).count()
def get_name(self, user):
return user.profile.name
def get_description(self, user):
return user.profile.description
def get_url(self, user):
return user.profile.url
def get_location(self, user):
return user.profile.location
class Meta:
model = User
fields = ('path', 'id', 'username', 'name', 'description', 'url', 'location', 'is_active',
'facebook_id', 'twitter_id', 'email',
'feed', 'timeline', 'following', 'followers',
'posts_count', 'following_count', 'followers_count')
I'm 100% that the URL bindings are correct for the API. When I try to GET a list of users I get the following error however:
Manager isn't available; User has been swapped for 'api.User'
Does anybody have any idea about what's going on here? I'm using Django 1.7.1 on Python 2.7.6.
Thanks in advance for any help!
Kind regards, K.
Upvotes: 2
Views: 2194
Reputation: 56
Instead of referring to User directly, you should reference the user model using django.contrib.auth.get_user_model(). This method will return the currently active User model – the custom User model if one is specified, or User otherwise.
Kinda late but nonetheless...
Upvotes: 4