Braek
Braek

Reputation: 601

Django REST Framework: Manager isn't available; User has been swapped for 'api.User'

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

Answers (1)

lurker
lurker

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

Related Questions