Search code examples
djangoauthenticationuser-inputuserformwagtail

Role choice field data ins't saved for UserRegsitrationForm django


The following error message appears after I submit the SignUpform:

'NoneType' object has no attribute '_inc_path' This issue is related to the role choice field of my CustomUser model. The models function perfectly without the role field and all forms are displayed and saved correctly. I suspect my choice field form does not pass/save correctly the input values to the CustomUser model.

Any input would be highly appreciated.

Models.py:


class CustomUser(AbstractUser):
    display_name = models.CharField(verbose_name=("Display name"), max_length=30, help_text=("Will be shown e.g. when commenting"))
    ...
    country = CountryField(blank=True, null=True)
    ...
    role = models.CharField(choices = ROLES, max_length = 50, default = "regular_user",)
    ...

class Meta:
        ordering = ['last_name']

    def get_absolute_url(self):
        return reverse('account_profile')

    def __str__(self):
        return f"{self.username}: {self.first_name} {self.last_name}" ``` 

forms.py:

class SignupForm(forms.Form):
    first_name = forms.CharField(max_length=30, label=_("First name"))
    last_name = forms.CharField(max_length=30, label=_("Last name"))
    display_name = forms.CharField(max_length=30, label=_("Display name"), help_text=_("Will be shown e.g. when commenting."))
    role = forms.ChoiceField(choices = ROLES, label="Role", initial='Regular_user', widget=forms.Select(), required=True)

    def signup(self, request, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.display_name = self.cleaned_data['display_name']
        user.role = self.cleaned_data['role']
        user.save() 

users/create.html:

{% extends "wagtailusers/users/create.html" %}
{% block extra_fields %}
    ...
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.role %}
...
{% endblock extra_fields %}
 
settings.py:
 
AUTH_USER_MODEL = 'userauth.CustomUser'
WAGTAIL_USER_CREATION_FORM ='userauth.forms.WagtailUserCreationForm'
WAGTAIL_USER_EDIT_FORM = 'userauth.forms.WagtailUserEditForm'
WAGTAIL_USER_CUSTOM_FIELDS = ['display_name',... 'role', ...]
ACCOUNT_SIGNUP_FORM_CLASS = 'userauth.forms.SignupForm' 


Error log:
2022-10-17 10:16:35,894: Internal Server Error: /accounts/signup/
Traceback (most recent call last):
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/django/views/generic/base.py", line 84, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/django/utils/decorators.py", line 46, in _wrapper
    return bound_method(*args, **kwargs)
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/allauth/decorators.py", line 20, in wrap
    resp = function(request, *args, **kwargs)
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/django/utils/decorators.py", line 46, in _wrapper
    return bound_method(*args, **kwargs)
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/django/views/decorators/debug.py", line 92, in sensitive_post_parameters_wrapper
    return view(request, *args, **kwargs)
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/allauth/account/views.py", line 234, in dispatch
    return super(SignupView, self).dispatch(request, *args, **kwargs)
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/allauth/account/views.py", line 77, in dispatch
    response = super(RedirectAuthenticatedUserMixin, self).dispatch(
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/allauth/account/views.py", line 207, in dispatch
    return super(CloseableSignupMixin, self).dispatch(request, *args, **kwargs)
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/django/views/generic/base.py", line 119, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/allauth/account/views.py", line 105, in post
    response = self.form_valid(form)
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/allauth/account/views.py", line 252, in form_valid
    return complete_signup(
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/allauth/account/utils.py", line 183, in complete_signup
    signals.user_signed_up.send(
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/django/dispatch/dispatcher.py", line 176, in send
    return [
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/django/dispatch/dispatcher.py", line 177, in <listcomp>
    (receiver, receiver(signal=self, sender=sender, **named))
  File "/home/teki/fommestyuta/users/models.py", line 38, in create_user_group_and_pages
    home.add_child(instance=article_index_page)
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/treebeard/mp_tree.py", line 1083, in add_child
    return MP_AddChildHandler(self, **kwargs).process()
  File "/home/teki/.virtualenvs/bup/lib/python3.9/site-packages/treebeard/mp_tree.py", line 377, in process
    newobj.path = self.node.get_last_child()._inc_path()
AttributeError: 'NoneType' object has no attribute '_inc_path'


create_user_group_and_pages:

from django.db import models
from django.contrib.auth.models import Group, Permission
from django.dispatch import receiver
from allauth.account.signals import user_signed_up
from wagtail.core.models import Page, GroupPagePermission, GroupCollectionPermission, Collection
from cms.models import ArticleIndexPage

@receiver(user_signed_up)
def create_user_group_and_pages(sender, **kwargs):
    """
    When a new user signs up create a unique group and page for them.
    Assign it the appropriate permission for admin, page and collection access.
    """

    # Grab the new user
    user = kwargs['user']

    # Create a group object that matches their username
    new_group, created = Group.objects.get_or_create(name=user.username)

    # Add the new group to the database
    user.groups.add(new_group)

    # Create new permission to access the wagtail admin
    access_admin = Permission.objects.get(codename='access_admin')

    # Add the permission to the group
    new_group.permissions.add(access_admin)

    # Now start creating page access
    # First find the homepage
    home = Page.objects.get(slug='home').specific

    # Create unique PersonIndexPage for the user
    article_index_page = ArticleIndexPage(title=user.username)

    # Add PersonIndexPage to homepage as a child
    home.add_child(instance=article_index_page)

    # Save new page as first revision
    article_index_page.save_revision()

    # Create new add GroupPagePermission
    GroupPagePermission.objects.create(
        group=new_group,
        page=article_index_page,
        permission_type='add'
    )

    # Create new GroupCollectionPermission for Profile Images collection
    GroupCollectionPermission.objects.create(
        group=new_group,
        collection=Collection.objects.get(name='Images'),
        permission=Permission.objects.get(codename='add_image')
    )


Solution

  • It looks like the page tree data in your database has become inconsistent, causing it to fail when creating the new ArticleIndexPage. (Specifically, the record for the 'home' page shows that it has existing child pages, meaning that it has to look at those child page records to find the correct position for the new page - but when it tries retrieving those child pages, none are being returned.) This may have happened due to a previous error occurring part-way through creating or deleting a page.

    To fix this, run: ./manage.py fixtree