ubernostrum / django-registration

An extensible user-registration app for Django.
BSD 3-Clause "New" or "Revised" License
923 stars 241 forks source link

False ImproperlyConfigured error #233

Closed pepijnstemerding closed 2 years ago

pepijnstemerding commented 2 years ago

Hey,

using:

I carefully read all the documentation regarding using this and Custom User models, and of it came the following applicable code:

settings.py:

INSTALLED_APPS = [
    ...
    'django.contrib.auth',
    'django_registration',
    ...
]

AUTH_USER_MODEL = 'users.CustomUser'

ACCOUNT_ACTIVATION_DAYS = 7

users/forms.py:

from django_registration.forms import RegistrationForm

from .models import CustomUser

class CustomRegisterForm(RegistrationForm):
    class Meta(RegistrationForm.Meta):
        model = CustomUser
        fields = ('email', 'first_name', 'last_name', 'phone', 'password1', 'password2')

users/urls.py:

from django.urls import include, path
from django_registration.backends.activation.views import RegistrationView

from .forms import CustomRegisterForm

urlpatterns = [
    path('', include('django_registration.backends.activation.urls')),
    path('', include('django.contrib.auth.urls')),
    path('register/',
        RegistrationView.as_view(
            form_class=CustomRegisterForm
        ),
        name='django_registration_register',
    ),
]

my CustomUserManager:

class CustomUserManager(BaseUserManager):
    """Taken default and removed the username fields, added phone and email
    """
    use_in_migrations = True

    def _create_user(self, email, password, phone=None, **extra_fields):
        email = self.normalize_email(email)
        user = self.model(
            email=email,
            phone=phone,
            **extra_fields
        )
        user.password = make_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, phone=None, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", False)
        extra_fields.setdefault("is_superuser", False)
        return self._create_user(email, password, phone, **extra_fields)

    def create_superuser(self, email, phone=None, password=None, **extra_fields):
        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, phone, **extra_fields)

    def with_perm(
        self, perm, is_active=True, include_superusers=True, backend=None, obj=None
    ):
        if backend is None:
            backends = auth._get_backends(return_tuples=True)
            if len(backends) == 1:
                backend, _ = backends[0]
            else:
                raise ValueError(
                    "You have multiple authentication backends configured and "
                    "therefore must provide the `backend` argument."
                )
        elif not isinstance(backend, str):
            raise TypeError(
                "backend must be a dotted import path string (got %r)." % backend
            )
        else:
            backend = auth.load_backend(backend)
        if hasattr(backend, "with_perm"):
            return backend.with_perm(
                perm,
                is_active=is_active,
                include_superusers=include_superusers,
                obj=obj,
            )
        return self.none()

my CustomUser model:

class CustomUser(AbstractUser, PermissionsMixin):
    username = None
    first_name = models.CharField(
        verbose_name=_('Voornaam'),
        max_length=150
    )
    last_name = models.CharField(
        verbose_name=_('Achternaam'),
        max_length=150
    )
    email = models.EmailField(
        verbose_name=_('Email adres'),
        unique=True
    )
    phone = PhoneNumberField(
        verbose_name=_('Telefoon nummer'),
        blank=True,
        unique=True,
        null=True
    )

    USERNAME_FIELD = 'email'
    EMAIL_FIELD = 'email'
    REQUIRED_FIELDS = []
    objects = CustomUserManager()

    class Meta:
        verbose_name = _('Gebruiker')
        verbose_name_plural = _('Gebruikers')

But I still get the follow error:

Internal Server Error: /nl/gebruikers/register/
Traceback (most recent call last):
  File "C:\...\Python\Python310\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
  File "C:\...\Python\Python310\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\...\Python\Python310\lib\site-packages\django\views\generic\base.py", line 84, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\...\Python\Python310\lib\site-packages\django\utils\decorators.py", line 46, in _wrapper
    return bound_method(*args, **kwargs)
  File "C:\...\Python\Python310\lib\site-packages\django\views\decorators\debug.py", line 92, in sensitive_post_parameters_wrapper
    return view(request, *args, **kwargs)
  File "C:\...\Python\Python310\lib\site-packages\django_registration\views.py", line 54, in dispatch
    return super().dispatch(*args, **kwargs)
  File "C:\...\Python\Python310\lib\site-packages\django\views\generic\base.py", line 119, in dispatch
    return handler(request, *args, **kwargs)
  File "C:\...\Python\Python310\lib\site-packages\django\views\generic\edit.py", line 144, in get
    return self.render_to_response(self.get_context_data())
  File "C:\...\Python\Python310\lib\site-packages\django\views\generic\edit.py", line 74, in get_context_data
    kwargs["form"] = self.get_form()
  File "C:\...\Python\Python310\lib\site-packages\django_registration\views.py", line 76, in get_form
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured:
You are attempting to use the registration view <class 'django_registration.backends.activation.views.RegistrationView'>
with the form class <class 'django_registration.forms.RegistrationForm'>,
but the model used by that form (<class 'django.contrib.auth.models.User'>) is not
your Django installation's user model (<class 'users.models.CustomUser'>).

Most often this occurs because you are using a custom user model, but
forgot to specify a custom registration form class for it. Specifying
a custom registration form class is required when using a custom user
model. Please see django-registration's documentation on custom user
models for more details.

But clearly I did specify the custom user model in settings and the custom registration form, so how do I fix this?

pepijnstemerding commented 2 years ago

Could anybody please help me with this, I genuinely dont understand what is wrong..

pepijnstemerding commented 2 years ago

My issue was that

path('', include('django_registration.backends.activation.urls')),

is before

    path('register/',
        RegistrationView.as_view(
            form_class=CustomRegisterForm
        ),
        name='django_registration_register',
    ),