8

I have created a different version of the User model where there is no username field and I am now trying to implement a sign in feature, but I keep getting the error

Manager isn't available; 'auth.User' has been swapped for 'polls.User'

I have searched the rest of this site and tried to implement the feature beneath to fix the problem but to no avail.

from django.contrib.auth import get_user_model

User = get_user_model()

Here is the rest of my files

Views

    from django.http import HttpResponse
    from django.shortcuts import get_object_or_404, render, render_to_response, redirect
    from django.contrib.auth.decorators import login_required
    from django.contrib.auth import login, authenticate
    from django.shortcuts import render, redirect

    from polls.forms import SignUpForm
    from django.contrib.auth import get_user_model

    User = get_user_model()

    @login_required
    def home(request):
        return render(request, 'home.html')

    def signup(request):
        if request.method == 'POST':
            form = SignUpForm(request.POST)
            if form.is_valid():
                form.save()
                username = None
                raw_password = form.cleaned_data.get('password1')
                user = authenticate(password=raw_password)
                login(request, user)
                return redirect('home')
        else:
            form = SignUpForm()
        return render(request, 'signup.html', {'form': form})

forms

from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User


class SignUpForm(UserCreationForm):
    first_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
    last_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
    email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
    username = None

    class Meta:
        model = User
        fields = ('first_name', 'last_name', 'email', 'password1', 'password2', )

models

from django.db import models
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db import models
from django.utils.translation import ugettext_lazy as _

class UserManager(BaseUserManager):
    """Define a model manager for User model with no username field."""

    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        """Create and save a User with the given email and password."""
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        """Create and save a regular User with the given email and password."""
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        """Create and save a SuperUser with the given email and password."""
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)


class User(AbstractUser):
    """User model."""

    username = None
    email = models.EmailField(_('email address'), unique=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()

If anyone could provide any clarity on this it would be greatly appreciated

Ethan Pearce
  • 139
  • 2
  • 3
  • 8

3 Answers3

21

In your forms.py you have to also change

from django.contrib.auth.models import User

to

from django.contrib.auth import get_user_model

User = get_user_model()

This goes for everywhere you use User. The traceback of the error will tell you exactly where the error was caused. When seeking help debugging, always include the traceback in the question.

Håken Lid
  • 22,318
  • 9
  • 52
  • 67
  • Thank you!!! I have found several other posts with similar solutions and no one was able to write a simple solution without paragraphs of gibberish. Thanks for keeping it simple! - This solved my problem immediately. – Michael Romrell Dec 03 '18 at 19:26
1

Edited: Never mind, see Håken Lid answer. I misread the problem.

But, nonetheless you have to fix the code below as well


Depends on what Django version you are using, but the problem is in this line:

user = authenticate(password=raw_password)

You should pass also the username:

user = authenticate(username='john', password='secret')

Then, then authenticate method will return either a User instance or None.

if user is not None:
    login(request, user)
else:
    # authenticated failed
Vitor Freitas
  • 3,550
  • 1
  • 24
  • 35
  • Thank you, Vitor, When you are saying username='john', password='secret', I assume that translates to username=username, password=raw_password. I apologize if this is a stupid question I'm rather new at Django – Ethan Pearce Feb 16 '18 at 10:14
  • Yes, that's correct, there you would use the **username** and **raw_password**. But in your case maybe you will need to pass the email, instead of the username. Because you removed the username from the model. – Vitor Freitas Feb 16 '18 at 10:28
  • This looks like the code from Practical Django 2 and Channels 2 – Mitch Feb 15 '19 at 15:19
-2

take a look here it been solved by others. [solution on stackoverflow Link

nsola
  • 765
  • 6
  • 8