AttributeError at /register Manager isn't available; 'auth.User' has been swapped for 'account.Account'

Viewed 567

I have been working on debugging this code for last 2 days but not able to find out the mistake. I have seen the tried the user = get_user_model() but it is not working.

Also i have added in settings

AUTH_USER_MODEL = 'account.Account'

and account is a registered app in settings.

models.py

from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
from django.conf import settings



# account manager 
class MyAccountManager(BaseUserManager):
    def create_user(self, email, username, profile, password=None):
        if not email:
            raise ValueError('Users must have an email address')
        if not username:
            raise ValueError('Users must have a username')

        user = self.model(
            email=self.normalize_email(email),
            username=username,
            profile_image=profile
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, username, password):
        user = self.create_user(
            email=self.normalize_email(email),
            password=password,
            username=username,
        )
        user.is_admin = True
        user.is_staff = True
        user.is_superuser = True
        user.save(using=self._db)
        return user




# models here.

def uploadImageHandler(instance,filename):
    fpath = pathlib.Path(filename)
    newFileName = str(uuid.uuid1())
    return f"images/profile/{newFileName}{fpath.suffix}"



class Account(AbstractBaseUser):
    email                   = models.EmailField(verbose_name="email", max_length=60, unique=True)
    username                = models.CharField(max_length=30, unique=True)
    firstName               = models.CharField(max_length=30)
    lastName                = models.CharField(max_length=30)
    date_joined             = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
    last_login              = models.DateTimeField(verbose_name='last login', auto_now=True)
    is_admin                = models.BooleanField(default=False)
    is_active               = models.BooleanField(default=True)
    is_staff                = models.BooleanField(default=False)
    is_superuser            = models.BooleanField(default=False)
    profile_image           = models.ImageField(max_length=255, upload_to=uploadImageHandler, null=True, blank=True)
    hide_email              = models.BooleanField(default=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    objects = MyAccountManager()

    def __str__(self):
        return self.username

    def has_perm(self, perm, obj=None):
        return self.is_admin

    def has_module_perms(self, app_label):
        return self.is_admin 

forms.py

from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import authenticate , login , logout

# import from app
from account.models import Account

class RegistrationForm(UserCreationForm):
    email       = forms.EmailField(max_length=255, required=True, help_text="Enter a valid email ")
    class meta:
        model = Account
        fields = ('email','username','password1','password2','profile')
    

    def clean_email(self):
        email = self.cleaned_data["email"].lower()
        try:
            account = Account.objects.get(email=email)
        except:
            return email
        raise forms.ValidationError(f"email{email} is already in use.")
    
    def clean_username(self):
        username = self.cleaned_data["username"]
        try:
            account = Account.objects.get(username=username)
        except:
            return username
        raise forms.ValidationError(f"email{username} is already in use.")

views.py

# django imports 
from django.shortcuts import render , HttpResponse, redirect
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model


# app imports 
from .forms import RegistrationForm


# Create your views here.
user = get_user_model()

# register page here

def register_view(request, *args, **kwargs):
    context = {}
    user = request.user
    if user.is_authenticated:
        return redirect("home")
    elif (request.method == 'POST'):
        print("hello")
        form = RegistrationForm(request.POST)
        print(form)
        if form.is_valid():
            form.save()
            email = form.cleaned_data.get('email').lower()
            raw_password = form.cleaned_data.get('password1')
            account = authenticate(email=email,password=raw_password)
            login(request,account)
            destination = kwargs.get("next")
            if destination:
                return redirect(destination)
            else:
                pass
        else:
            context['registration_form'] = form

    else:
        form = RegistrationForm()
        context['registration_form'] = form
    return render(request, 'account/register.html',context)

error

Traceback (most recent call last):
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/mnt/d/Working/artoction/artoction/account/views.py", line 54, in register_view
    print(form)
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/utils/html.py", line 376, in <lambda>
    klass.__str__ = lambda self: mark_safe(klass_str(self))
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/forms.py", line 132, in __str__
    return self.as_table()
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/forms.py", line 270, in as_table
    return self._html_output(
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/forms.py", line 193, in _html_output
    top_errors = self.non_field_errors().copy()
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/forms.py", line 304, in non_field_errors
    return self.errors.get(NON_FIELD_ERRORS, self.error_class(error_class='nonfield'))
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/forms.py", line 170, in errors
    self.full_clean()
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/forms.py", line 374, in full_clean
    self._post_clean()
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/contrib/auth/forms.py", line 117, in _post_clean
    super()._post_clean()
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/models.py", line 413, in _post_clean
    self.instance.full_clean(exclude=exclude, validate_unique=False)
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/db/models/base.py", line 1223, in full_clean
    self.clean()
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/contrib/auth/models.py", line 371, in clean
    self.email = self.__class__.objects.normalize_email(self.email)
  File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/db/models/manager.py", line 187, in __get__
    raise AttributeError(
AttributeError: Manager isn't available; 'auth.User' has been swapped for 'account.Account'

error as shown in the browser

1 Answers

The problem comes from your register view, you have imported the "from django.contrib.auth import get_user_model" and "from django.contrib.auth.models import User" which you need to take out from your imports models.

# django imports 
from django.shortcuts import render , HttpResponse, redirect
from django.contrib.auth import authenticate, login
#from django.contrib.auth.models import User this where where your problem comes from
# from django.contrib.auth import get_user_model 
# now you would need to import the Account model since you are not using djangos build in User model 
from account.models import Account 


# app imports 
from .forms import RegistrationForm


# Create your views here.
# user = get_user_model() You would have to delete this or just comment it out .

# register page here

def register_view(request, *args, **kwargs):
    context = {}
    user = request.user
    if user.is_authenticated:
        return redirect("home")
    elif (request.method == 'POST'):
        print("hello")
        form = RegistrationForm(request.POST)
        print(form)
        if form.is_valid():
            form.save()
            email = form.cleaned_data.get('email').lower()
            raw_password = form.cleaned_data.get('password1')
            account = authenticate(email=email,password=raw_password)
            login(request,account)
            destination = kwargs.get("next")
            if destination:
                return redirect(destination)
            else:
                pass
        else:
            context['registration_form'] = form

    else:
        form = RegistrationForm()
        context['registration_form'] = form
    return render(request, 'account/register.html',context)

I also observed that you have an attribute in your models manager filed which is not in your account field, which in think would raise exception of attribute error when your try to create an account so i so guess you delete the profile attribute from your manager and also from your form. Here is my solution .

class MyAccountManager(BaseUserManager):
    def create_user(self, email, username, password=None):
        if not email:
            raise ValueError('Users must have an email address')
        if not username:
            raise ValueError('Users must have a username')

Your form.py: Everything should now work perfectly hopefully!

class RegistrationForm(UserCreationForm):
    email       = forms.EmailField(max_length=255, required=True, help_text="Enter a valid email ")
    class meta:
        model = Account
        fields = ('email','username','password1','password2')
    

    def clean_email(self):
        email = self.cleaned_data["email"].lower()
        try:
            account = Account.objects.get(email=email)
        except:
            return email
        raise forms.ValidationError(f"email{email} is already in use.")
    
    def clean_username(self):
        username = self.cleaned_data["username"]
        try:
            account = Account.objects.get(username=username)
        except:
            return username
        raise forms.ValidationError(f"email{username} is already in use.")

        user = self.model(
            email=self.normalize_email(email),
            username=username,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, username, password):
        user = self.create_user(
            email=self.normalize_email(email),
            password=password,
            username=username,
        )
        user.is_admin = True
        user.is_staff = True
        user.is_superuser = True
        user.save(using=self._db)
        return user
Related