Hello I am trying to extend Django User model using Abstract User but I get OperationalError when signing up
Error:
OperationalError at /main/signup/
no such column: main_profile.username
My Profile model:
class Profile(AbstractUser):
email = models.EmailField(max_length=150)
bio = models.TextField()
university = models.CharField(max_length=30)
def __str__(self):
return self.username
CREATED = 0
ACTIVE = 1
BANNED = 2
KICKED = 3
UPGRADE = 4
STS = (
(CREATED, 'Just Created'),
(ACTIVE, 'Activated'),
(BANNED, 'Disabled'),
(KICKED, 'Disabled'),
(UPGRADE, 'Active'),
)
status = models.IntegerField(choices=STS, default=CREATED, blank=True, null=True)
My Signup form:
class SignUpForm(UserCreationForm):
username = forms.CharField(
label='',
max_length=30,
min_length=5,
required=True,
widget=forms.TextInput(
attrs={
"placeholder": "Username",
"class": "form-control"
}
)
)
first_name = forms.CharField(
label='',
max_length=50,
min_length=2,
required=True,
widget=forms.TextInput(
attrs={
"placeholder": "First name",
"class": "form-control"
}
)
)
last_name = forms.CharField(
label='',
max_length=50,
min_length=2,
required=True,
widget=forms.TextInput(
attrs={
"placeholder": "Last name",
"class": "form-control"
}
)
)
university = forms.CharField(
label='',
max_length=50,
min_length=2,
required=False,
widget=forms.TextInput(
attrs={
"placeholder": "University",
"class": "form-control"
}
)
)
email = forms.EmailField(
label='',
max_length=255,
required=True,
widget=forms.EmailInput(
attrs={
"placeholder": "Email",
"class": "form-control"
}
)
)
password1 = forms.CharField(
label='',
max_length=30,
min_length=8,
required=True,
widget=forms.PasswordInput(
attrs={
"placeholder": "Password",
"class": "form-control"
}
)
)
password2 = forms.CharField(
label='',
max_length=30,
min_length=8,
required=True,
widget=forms.PasswordInput(
attrs={
"placeholder": "Confirm Password",
"class": "form-control"
}
)
)
class Meta:
model = Profile
fields = ('username', 'first_name', 'last_name', 'email','university',)
def save(self, commit=True):
user = super(UserCreationForm,self).save(commit = False)
user.email = self.cleaned_data['email']
user.university = self.cleaned_data['university']
if commit:
user.save()
return user
My Signup view:
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
user.refresh_from_db() # load the profile instance created by the signal
user.profile.university = form.cleaned_data.get('university')
user.save()
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
#user_login(request, user)
return redirect('main:main_page')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
I have also added tis in setting already
AUTH_USER_MODEL = 'main.Profile'
I do not understand why there is an error should AbstractUser already provide username? Or do I have to add all the fields to the Profile model, even the passwords?
Below is also my custom edit profile - I do not know if it is correct however:
class EditProfileForm(UserChangeForm):
username = forms.CharField(
label='',
max_length=50,
min_length=2,
required=False,
widget=forms.TextInput(
attrs={
"placeholder": "Username",
"class": "form-control"
}
)
)
first_name = forms.CharField(
label='',
max_length=50,
min_length=2,
required=False,
widget=forms.TextInput(
attrs={
"placeholder": "First name",
"class": "form-control"
}
)
)
last_name = forms.CharField(
label='',
max_length=50,
min_length=2,
required=False,
widget=forms.TextInput(
attrs={
"placeholder": "Last name",
"class": "form-control"
}
)
)
university = forms.CharField(
label='',
max_length=50,
min_length=2,
required=False,
widget=forms.TextInput(
attrs={
"placeholder": "University",
"class": "form-control"
}
)
)
email = forms.EmailField(
label='',
max_length=255,
required=False,
widget=forms.EmailInput(
attrs={
"placeholder": "Email",
"class": "form-control"
}
)
)
bio = forms.CharField(
required=False,
widget=forms.Textarea(
attrs={
"placeholder":"Enter something about yourself",
"class": "form-control"
}
)
)
password = None
class Meta:
model = Profile
fields=('username','first_name','last_name','email','bio',)
def save(self, commit = True):
user = super(UserChangeForm, self).save(commit=False)
user.bio = self.cleaned_data['bio']
if commit:
user.save()
return user
Thanks in advance for all the help!
When you use AbstractUser
it give you predefine User
model fields + New fields
that you define in model extend time
here when you extend user model not need to define email field explicitly due to 'User model' Have this field and when you use UserCreationForm
it also have all pre-define field you don't need to Redefine it, In your case you define username,first_name,last_name,email
it's not need,but if you want to take input of extra field then, you need to define extra field that you add in your model like university
or bio
and if you need to add placeholder
or bootstrap classes
you use pre_define method def __init__
i give you stuff apply it's in you code
@model.py
class Profile(AbstractUser):
# remove email fields
bio = models.TextField()
university = models.CharField(max_length=30)
def __str__(self):
return self.username
@form.py
class SignUpForm(UserCreationForm):
university=formforms.CharField(label='',max_length=50,min_length=2)
class Meta:
model = Profile
fields = ('username', 'first_name', 'last_name', 'email','university',)
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
for field in self.fields:
self.fields[field].widget.attrs.update({'class':'form-control','placeholder':self.fields[field].label})
@views.py
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
return redirect('main:main_page')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
apply above stuff and let me know if work or not