My aim - Trying to create an authentication system in Django, and allows user to signup again with same username if their account is not activated.
If an user try to register with a certain username and that username already exists then update that user with this current user.
My Approach - I have created a form using "UserCreationForm" and defining my own methods to validate the form, and allows the user even if username already exists but user.is_active = False.
Code
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import User
class SignupForm(UserCreationForm):
email = forms.EmailField(max_length=200, help_text='Required')
name = forms.CharField()
institution = forms.CharField()
def clean_username(self):
username = self.cleaned_data.get('username')
user = None
try:
try:
user = User.objects.get(username=username)
print("is user active username", user.is_active)
except ObjectDoesNotExist as e:
pass
except Exception as e:
raise e
if not user:
pass
elif not user.is_active:
pass
else:
raise forms.ValidationError("This Username Already Exists")
except Exception as e:
raise e
return username
class Meta:
model = User
fields = ('username', 'email', 'institution', 'password1', 'password2')
views.py
from .forms import SignupForm
def regUser(form):
'''
It will save Django user and student.
It recieves form.cleaned_data as argument
'''
print("reg user line 1")
user = User.objects.create_user(username=form['username'],
email=form['email'],
password=form['password1'],
is_active=False,
)
# notice is_active = False, becuase we will activate account if user will
# verify the email
user.save()
student = Student(user=user, name=form['name'], institution=form['institution'])
student.save()
return user
def signup(request):
if request.user.is_authenticated:
return redirect('accounts:home')
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
user = regUser(form.cleaned_data)
current_site = get_current_site(request)
message = render_to_string('accounts/acc_active_email.html', {
'user':user, 'domain':current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
})
mail_subject = 'Activate your account.'
to_email = form.cleaned_data.get('email')
email = EmailMessage(mail_subject, message, to=[to_email])
email.send()
return render(request, 'accounts/signup.html', {'email_sent': True})
else:
for field in form:
for error in field.errors:
messages.error(request, error)
return redirect("accounts:signup")
return render(request, 'accounts/signup.html')
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
subject = models.CharField(max_length=250, default="default_value")
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
name = models.CharField(max_length=250, default="default_value")
institution = models.CharField(max_length=250, default="default_value")
def save(self):
super().save()
def __str__(self):
return self.user.username
My problem - I am getting error " A user with that username already exists" I don't why and from where this error is coming when I am trying to created a new user with already registered username but it account is not activated yet (user.is_active = False).
As much I know clean_fields functions are called to validate the form when we use "form.is_valid()" in our views.py, But I have already overridden the "clean_username" according to my need so why I am getting this error ? and from where it is generated ? and how to solve this ?
Also I would like to mention when user is registered it is also registered "student" that's why I am using "regUser" function. Also I read some other questions similar to this on stackoverflow this and this some answer was that inherit the form from "forms.Form" not from "UserCreationForm" but why can anyone explain?
Please not mark this question as already answered I have gone through all questions and it was not helpful.