Search code examples
pythondjangodjango-modelsdjango-formsdjango-users

Data not storing in database for choice field for UserRegsitrationForm django


I have extended the UserCreationForm of Django to add extra fields : Email and Choice field. Now when I am filling those details in the registration form and submitting it. Only the email is stored in the database and not the choice field(i.e status in the code). However when I am viewing the fields of my form in the console the choice field is showing. But when I am accessing the attribute using the django shell I am getting an error

from django.contrib.auth.models import User
users = User.objects.all()
users[6].email
Output : [email protected] # success

users[6].status
Error: AttributeError                            Traceback (most recent call last)
<ipython-input-7-c9d2701fa919> in <module>()
----> 1 users[6].status

AttributeError: 'User' object has no attribute 'status'

Here is my forms.py

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

class SignUpForm(UserCreationForm):
    STATUS_CHOICES = (
        (1, ("CEO")),
        (2, ("Dev Manager")),
        (3, ("Testing Manager")),
        (4, ("Developer")),
        (5, ("Test Engineer"))
    )
    email = forms.EmailField(required=True,
                         label='Email',
                         error_messages={'exists': 'Oops'})
    status = forms.ChoiceField(choices = STATUS_CHOICES, label="Designation", initial='Developer', widget=forms.Select(), required=True)



    class Meta:
        model = User
        fields = ("username", "email", "password1", "password2", "status")

        def save(self, commit=True):
            user = super(UserCreateForm, self).save(commit=False)
            user.email = self.cleaned_data["email"]
            user.status = self.cleaned_data["status"]
            if commit:
                user.save()
            return user

Why am I getting error?


Solution

  • It is not enough to add the field to your form, you also have to add it to the model.

    For that, you need to create a custom user class in your models.py:

    from django.contrib.auth.models import AbstractUser
    
    STATUS_CHOICES = (
        (1, ("CEO")),
        (2, ("Dev Manager")),
        (3, ("Testing Manager")),
        (4, ("Developer")),
        (5, ("Test Engineer"))
    )
    class User(AbstractUser):
        status forms.ChoiceField(choices = STATUS_CHOICES, verbose_name ="Designation")
    

    Then you have to change the settings AUTH_USER_MODEL to point to your model accordingly. Assuming the app which contains your new custom user model is called my_app, the setting would look like this:

    AUTH_USER_MODEL = 'my_app.User'
    

    You also have to make sure that any ForeignKey fields in your model use AUTH_USER_MODEL instead of django.contrib.auth.models.User:

    from django.conf import settings from django.db import models

    class Article(models.Model):
        author = models.ForeignKey(
            settings.AUTH_USER_MODEL,
            on_delete=models.CASCADE,
        )
    

    Also don't forget to create and apply database migrations:

    python manage.py makemigrations
    python manage.py migrate
    

    Unfortunately, changing the user model mid-project can lead to tricky problems, so if you are still early in your project, it might be easiest to delete and recreate your database.

    Refer to your model with get_user_model() in your form:

    from django.contrib.auth import get_user_model
    
    class SignUpForm(UserCreationForm):
        ...
    
        class Meta:
            model = get_user_model()
    

    Please refer to the documentation on Substituting a custom User model