0

I created a Profile model with Django. The profile inherits from a CustomUser class which I wrote by inheriting AbstractBaseUser. However, when I go to the sign up page, even though first_name and last_name are required in the Custom User class, it doesn't show. It only shows the fields of the profile model, and email and password. I am using Django all auth.

How do I make the required fields of the custom user (and other fields I want e.g middle_name) and the fields of the profile all show up in the same form, and still save both the custom user model, and the profile model in the database all at the same time?

models.py

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    
    USER_TYPE_CHOICES = (
      (1, 'student'),
      (2, 'department'),
      (3, 'admin'),     
    )
    
    first_name = models.CharField(max_length=70, blank=False, default="")     
    middle_name = models.CharField(max_length=70, blank=False, default="")         
    last_name = models.CharField(max_length=70, blank=False, default="")          
    is_active = models.BooleanField(default=True)    
    user_type = models.PositiveSmallIntegerField(choices=USER_TYPE_CHOICES)
    is_staff = models.BooleanField(default=False) # a admin user; non super-user
    is_superuser = models.BooleanField(default=False) # a superuser
    last_login = models.DateTimeField(null=True, blank=True)
    date_joined = models.DateTimeField(auto_now_add=True)      
    
    
    USERNAME_FIELD = 'email'
    EMAIL_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name'] # Email & Password are required by default.
    
    objects = UserManager()
    # I left out some unimportant code


class StudentUser(models.Model):
    # This is the model class for students
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    matric_number = models.CharField(max_length=11, blank=False)
    department = models.CharField(max_length=40, blank=False)
  

views.py:

from users.forms import StudentUserSignupForm
from allauth.account.views import SignupView

class StudentUserSignupView(SignupView):
    # The referenced HTML content can be copied from the signup.html
    # in the django-allauth template folder
    template_name = 'account/signup.html'
    # the previously created form class
    form_class = StudentUserSignupForm

forms.py:

class UserCreationForm(forms.ModelForm):
    """
    A form for creating new users. Includes all the required
    fields, plus a repeated password.
    """   

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

    def save(self, commit=True):        
        user = super(UserChangeForm, self).save(commit=False)
        # Save the provided password in hashed format
        if self.cleaned_data.get("password1"):
            user.set_password(self.cleaned_data["password1"])
                                                        
        if commit:                                                                    
            user.save()            

        return user
    # I removed some unimportant code

class StudentUserSignupForm(SignupForm):
    first_name = forms.CharField(max_length=70)     
    middle_name = forms.CharField(max_length=70, required=False)         
    last_name = forms.CharField(max_length=70)           
    matric_no = forms.CharField(min_length=10, max_length=11)
    department = forms.CharField(max_length=40)
    
    
    def save(self, request):
        # Save the User instance and get a reference to it
        user_form = super(StudentUserSignupForm, self).save(request)
        # user_form.user_type = 1 To correct
        
        student_user = StudentUser(
            user=user_form,
            matric_no=self.cleaned_data.get('matric_number'),
            department=self.cleaned_data.get('department')
        )
        student_user.save()
       
        return student_user.user

html template

<div class="row justify-content-center align-items-center">  
    <div class="col-auto m-auto">
      <div class="jumbotron mt-4">
        <h3>Sign Up</h3>
        <form method="post">
          {% csrf_token %}
          
          {% for field in form %}
            {{ field|add_class:"form-control-sm"|as_crispy_field }}
          {% endfor %}             
          <button class="btn btn-sm btn-primary" type="submit">Sign Up</button>
        </form>
      </div>
    </div>      

enter image description here

You see that in the image above, it shows email, password, and department, but it does not show first_name, last_name, middle_name etc. How do I make the required and non required fields of the User model show up in the form and still save both models? Does the issue have anything to do with django-allauth?

David.B
  • 370
  • 6
  • 16

0 Answers0