I have been trying to do my login and register on the sane template, but have been having issues with it. please i need some help. Below are my codes:
views.py:
def register_user(request):
if request.user.is_authenticated():
return redirect('home')
if request.method == 'POST':
rform = RegistrationForm(request.POST)
if rform.is_valid():
user = User.objects.create_user()
user.username = rform.cleaned_data['email']
user.set_password(rform.cleaned_data['password'])
user.first_name = rform.cleaned_data['first_name']
user.last_name = rform.cleaned_data['last_name']
user.email = rform.cleaned_data['email']
user.gender = rform.cleaned_data['gender']
user.save()
loggedin_user = authenticate(email = rform.cleaned_data['email'],
password = rform.cleaned_data['password'])
if user is not None:
login(request, loggedin_user)
return redirect('home')
else:
return render(request, 'accounts/access.html', {'rform': RegistrationForm()})
else:
return render(request, 'accounts/access.html', {'rform': RegistrationForm()})
else:
form = RegistrationForm()
return render(request, 'accounts/access.html', {'rform':form})
def login_now(request, *args, **kwargs):
if request.user.is_authenticated():
return redirect('home')
if request.method == "POST":
form = AuthenticationForm(request.POST)
if form.is_valid():
username = form.cleaned_data['email']
password = form.cleaned_data['password']
user = authenticate(username = form.cleaned_data['email'], password = password)
if user is not None:
login(request, user)
return redirect('home')
else:
return render(request, 'accounts/access.html', {'form': AuthenticationForm(), 'rform':RegistrationForm(), 'next':reverse_lazy('home')})
else:
return render(request, 'accounts/access.html', {'form': AuthenticationForm(), 'rform':RegistrationForm(), 'next':reverse_lazy('home')})
else:
return render(request, 'accounts/access.html', {'form': AuthenticationForm(), 'rform':RegistrationForm(), 'next':reverse_lazy('home')})
forms.py:
CHOICES = [
('Male', "Male"),
('Female', "Female"),
]
class RegistrationForm(forms.Form):
first_name = forms.CharField(max_length=25, widget=forms.TextInput(attrs={'placeholder': 'First name'}))
last_name = forms.CharField(max_length=25, widget=forms.TextInput(attrs={'placeholder': 'Last name'}))
email = forms.EmailField(max_length=50, widget=forms.TextInput(attrs={'placeholder': 'Email'}))
password = forms.CharField(max_length=25, widget=forms.PasswordInput(attrs={'placeholder': 'Password'}))
password1 = forms.CharField(max_length=25, widget=forms.PasswordInput(attrs={'placeholder': 'Password Confirm'}), label=("Re-type Password"))
gender = forms.ChoiceField(choices=CHOICES, widget=forms.RadioSelect(attrs={'placeholder': 'Gender'}))
class Meta:
model = ('User',)
def clean_email(self):
data = self.cleaned_data['email']
if User.objects.get(email=data):
raise forms.ValidationError('A user with this email already exist. You may recover the password with a password reset')
return data
def clean_password(self):
password = self.cleaned_data.get("password")
password1 = self.cleaned_data.get("password1")
if password1 and password and password1 != password:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
return password
access.html:
<div id = 'signup'>
<form id="post-form" action="{% url 'register' %}" method="POST">
{% csrf_token %}
<h3>REGISTER</h3>
<div>
{%for field in rform%}
<div style="margin-top:10px;">
{{field.label_tag}}<br/> {{field}}
{%if field.errors%} <br/>{{field.errors}} {%endif%}
</div>
{%endfor%}
</div>
<input type="submit" value="Register" class='sub' id='register'/>
</div>
<div id='login'>
{% if form.errors %}
{{ form.non_field_errors}}
{% endif %}
<form action='{% url 'login' %}' method='post' id ='signIn'>
{% csrf_token %}
<h3>SIGN IN</h3>
<p><label>Email:</label><br/>
{{ rform.email }}
{{ rform.email.errors }}</p>
<p><label>Password:</label><br/>
{{ rform.password }}
{{ rform.password.errors }}</p>
<p><input type="submit" value="login" id='submit' class='sub' /><br>
<input type="hidden" name="next" value="{% url 'home' %}" />
</form>
</div>
I try to register with the above and all i always get, is a redirection, please i need help.
Thanks in advance.
Please note, i extended the user profile that's why i have the gender in my registration form.
In your code, you are not comparing the right parameters
loggedin_user = authenticate(email = rform.cleaned_data['email'],
password = rform.cleaned_data['password'])
if user is not None:
login(request, loggedin_user)
return redirect('home')
You are checking an None variable, not the one returned by the authenticate ! if loggedin_user is not None is the correct check.
Check the example on the official doc.
You need to send the validated form rform so you can show the feedback (errors) to the user, you are sending a new form after the validation RegistrationForm()!
Also try to identify the source of the problem, you are posting your hole code but you don't know where the problem comes from, at least do some debugging ;) !
Related
i'm trying to signup with an otp for verification by sending email to the user mail, but getting this error, it's might be problem with signup.html, from where trying to get specific user otp to validate the data, if is there any better solution do this with django would be appreciate,
models.py
class User(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
is_buyer = models.BooleanField(default=False)
is_vendor = models.BooleanField(default=False)
objects = CustomUserManager()
def __str__(self):
return self.email
class UserOTP(models.Model):
user = models.ForeignKey(User, on_delete = models.CASCADE)
time_st = models.DateTimeField(auto_now = True)
otp = models.SmallIntegerField()
class Vendor(models.Model):
user = models.OneToOneField(User, related_name='vendor', on_delete=models.CASCADE)
business_name = models.CharField(max_length=50)
def __str__(self):
return self.user.email
forms.py
class VendorSignUpForm(UserCreationForm):
business_name = forms.CharField(required=True)
email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
class Meta:
model = User
fields = ('business_name', 'email', 'password1', 'password2', )
#transaction.atomic
def save(self):
user = super().save(commit=False)
user.is_vendor = True
user.save()
customer = Vendor.objects.create(user=user)
customer.business_name=self.cleaned_data.get('business_name')
customer.save()
return user
views.py
def signup(request):
if request.method == 'POST':
get_otp = request.POST.get('otp')
print(get_otp)
if get_otp:
get_user = request.POST.get('user')
user = User.objects.get(email=get_user)
if int(get_otp) == UserOTP.objects.filter(user = user).last().otp:
user.is_active = True
user.save()
messages.success(request, f'Account is Created For {user.email}')
return redirect('login')
else:
messages.warning(request, f'You Entered a Wrong OTP')
return render(request, 'registration/signup.html', {'otp': True, 'user': user})
form = VendorSignUpForm(request.POST)
if form.is_valid():
form.save()
email = form.cleaned_data.get('email')
user = User.objects.get(email=email)
print(user)
user.email = email
user.is_active = False
user.save()
usr_otp = random.randint(100000, 999999)
UserOTP.objects.create(user=user, otp = usr_otp)
mess = f"Hello {user.email},\nYour OTP is {usr_otp}\nThanks!"
send_mail( 'Welcome to Costume Base - Verify Your Email',
mess , settings.DEFAULT_FROM_EMAIL, [user.email],
fail_silently = False)
return render(request, 'registration/signup.html', {'otp': True, user: user})
else:
form = VendorSignUpForm()
return render(request, 'registration/signup.html', {'form': form})
signup.html
{% block content %}
<div>
<h2>Signup</h2>
</div>
<div>
{% if otp %}
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom display">
<h3 class="float-left">Verify Your Email</h3>
</legend>
** is this input value showing the error? **
<input type="hidden" value="{{user.email}}" name = 'user' >
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">OTP</span>
</div>
<input type="text" class="form-control" placeholder="Enter Your OTP" aria-label="OTP"
aria-describedby="basic-addon1" name = 'otp'>
</div>
</fieldset>
<div class="form-grounp">
<button class="btn mainbtn" type="submit">Verify</button>
<small class="float-right text-muted"><i><a href="#" class="text-dark"
onclick="ReSendOTP('{{user.email}}', 'resendOTPmess')"><i id="resendOTPmess">Resend</i> OTP</a></small>
</div>
</form>
{% else %}
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<button type="submit">Register</button>
</form>
</div>
{% endif %}
{% endblock content %}
From the Django documentation:
This exception is raised by the ORM when an expected object is not found. For example, QuerySet.get() will raise it when no object is found for the given lookups.
That's probably due to one of your Model.get() methods, e.g:
user = User.objects.get(email=get_user)
Try to handle it with a try/catch or use a .filter() method instead of .get()
Im trying to grab data from the url /register/?ref=123456 but having some trouble with it.
User registration is tied to one of my views:
class UserRegisterView(FormView):
form_class = UserRegisterForm
template_name = 'accounts/user_register_form.html'
success_url = '/accounts/login'
def form_valid(self, form):
username = form.cleaned_data.get('username')
email = form.cleaned_data.get('email')
password = form.cleaned_data.get('password')
new_user = User.objects.create(username=username, email=email)
new_user.set_password(password)
new_user.save()
ref = self.request.GET.get('ref', 'None')
print(ref)
return super(UserRegisterView, self).form_valid(form)
I'm trying to use "self.request.GET.get('ref', 'None')" to grab the data, but each time a user registers ref returns "None" rather than 123456
Here is the user_register_form.html:
<div class='row'>
<div class='col-sm-4 offset-sm-4 mt-3'>
<h1 class='text-center mt-3'>Sign Up</h1>
<form {% if form_id %} id='{{ form_id }}' {% endif %} class='form mt-3' method='POST' action=''>
{% csrf_token %}
{{ form|crispy }}
<input class='btn btn-primary-new' id="submit" type="submit" value="Sign Up" />
</form>
</div>
</div>
here's my solution guys:
I replaced
ref = self.request.GET.get('ref', 'None')
with
ref = (self.request.GET).dict()
data = ref['ref']
full implementation:
class UserRegisterView(FormView):
form_class = UserRegisterForm
template_name = 'accounts/user_register_form.html'
success_url = '/accounts/login'
def form_valid(self, form):
username = form.cleaned_data.get('username')
email = form.cleaned_data.get('email')
password = form.cleaned_data.get('password')
new_user = User.objects.create(username=username, email=email)
new_user.set_password(password)
new_user.save()
ref = (self.request.GET).dict()
data = ref['ref']
print(data)
return super(UserRegisterView, self).form_valid(form)
I was using django-registration-redux for my registration backend earlier and everything worked fine. I then decided to change the registration backend to django's default registration django.contrib.auth and the registration has been working fine but the login doesn't work. However, the thing is, only my superuser acoount can login, every other user can't login, both the regular users and the ones with staff clearance. It keeps giving me invalid username/password error.
Below is the login section of my views.py
def signin(request):
if request.user.is_authenticated:
return HttpResponseRedirect("/")
form = LoginForm()
errors = None
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
username = username.lower()
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
login(request, user)
if user.is_staff:
return redirect('sweet:vendor_index')
else:
return redirect('sweet:index')
else:
errors = "Invalid Username or Password"
return render(request, 'myregistration/signin.html', {'form':form, 'errors':errors})
Below is my signin.html
{% extends "base.html" %}
{% block title %}sign in{% endblock %}
{% block content %}
<h1>Sign in</h1>
{% if form.errors %}
<p class="error">Please correct the errors below:</p>
{{ errors }}
{% endif %}
<form method="post" action="{% url 'myregistration:signin' %}">{% csrf_token %}
<dl>
<dt><label for="id_username">Username:</label>{% if form.username.errors %} <span class="error">{{ form.username.errors|join:", " }}</span>{% endif %}</dt>
<dd>{{ form.username }}</dd>
<dt><label for="id_password">Password:</label>{% if form.password.errors %} <span class="error">{{ form.password.errors|join:", " }}</span>{% endif %}</dt>
<dd>{{ form.password }}</dd>
<dt><input type="submit" value="sign in" /></dt>
</dl>
</form>
<p>Forgotten password? Click here to reset password</p>
{% endblock %}
{% block content-related %}
<p>If you don't have an account, you can <a href="/accounts/register/">sign
up</a> for one.
{% endblock %}
And finally, my urls.py
from django.conf.urls import url
from myregistration import views
from django.contrib.auth import views as auth_views
app_name = 'myregistration'
urlpatterns = [
url(r'^register_vendor/', views.register_vendor, name='register_vendor'),
url(r'^register_customer/', views.register_customer, name='register_customer'),
url(r'^email_confirm/', views.email_confirm, name='email_confirm'),
url(r'^password_change/$', views.password_change, name='password_change'),
url(r'^password_reset/$', auth_views.password_reset, name='password_reset'),
url(r'^password_reset/done/$', auth_views.password_reset_done, name='password_reset_done'),
url(r'^signin/', views.signin, name='signin'),
url(r'^logout/', views.logout, name='logout'),
url(r'^activate/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', views.activate, name='activate'),
]
Below is my registration method
def register_customer(request):
registered = False
if request.method == 'POST':
customerform = CustomerSignUpForm(data=request.POST)
if customerform.is_valid():
customer = customerform.save(commit=False)
# Remeber to hash password again
customer.set_password(customer.password)
customer.is_active = False
customer.is_staff = False
customer.save()
text_content = "Account Activation Email"
mail_subject = "Activate your Juggernut account"
template_name = "myregistration/account_activate.html"
from_email = customerform.cleaned_data.get('email')
recipients = [customer.email]
kwargs = {
"uidb64":urlsafe_base64_encode(force_bytes(customer.pk)).decode(),
"token":account_activation_token.make_token(customer)
}
activation_url = reverse("myregistration:activate", kwargs=kwargs)
activation_url = "{0}://{1}{2}".format(request.scheme, request.get_host(), activation_url)
context = {
'customer':customer,
'activation_url':activation_url
}
html_content = render_to_string(template_name, context)
email=EmailMultiAlternatives(mail_subject, text_content, from_email, recipients)
email.attach_alternative(html_content, 'text/html')
email.send()
return redirect("myregistration:email_confirm")
registered=True
else:
print(customerform.errors)
else:
customerform = CustomerSignUpForm()
return render(request, 'myregistration/register_customer.html', {'customerform':customerform, 'registered':registered})
As you can see, in your views you have a form class to your view form = LoginForm(), but in your template you're not rendering this form and you won't be able to validate it and the line if form.is_valid(): will always return False.
You have two options, render the form class or change:
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
username = username.lower()
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
login(request, user)
if user.is_staff:
return redirect('sweet:vendor_index')
else:
return redirect('sweet:index')
else:
errors = "Invalid Username or Password"
to:
username = request.POST.get('username')
username = username.lower()
password = request.POST.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
if user.is_staff:
return redirect('sweet:vendor_index')
else:
return redirect('sweet:index')
Probably the LoginForm class take another parameters and cannot be validated
So when the form is invalid and I click submit, it just redirects to /home because of return redirect('/'). So what do I have to return here to prevent form submission and raise an error message? Here's my code:
views.py
class BoxesView(ListView, FormMixin):
template_name = 'polls.html' # extends base.html
form_class = UserRegistrationForm
def get_context_data(self, **kwargs):
context = super(BoxesView, self).get_context_data()
question_list = Question.objects.all().order_by('-date')
choice = Choice.objects.all()
context['question_list'] = question_list
context['choice'] = choice
q_list = []
returned_list = []
for i in question_list:
q_list.append(i)
for a, b in CATEGORY_CHOICES:
name = resolve(self.request.path_info).url_name
if b == name:
category = a
search = self.request.GET.get('search')
posts = Post.objects.all().filter(category=category).order_by('-date')
if search:
posts = posts.filter(
Q(title__icontains=search) |
Q(content__icontains=search)
)
else:
posts = Post.objects.all().filter(category=category).order_by('-date')
context['posts'] = posts
total = 0
for post in posts:
returned_list.append(post)
total += 1
if total == 4:
total = 0
for i in q_list:
returned_list.append(i)
q_list.remove(i)
break
paginator = Paginator(returned_list, 14)
page = self.request.GET.get('page')
try:
lst = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
lst = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
lst = paginator.page(paginator.num_pages)
context['lst'] = lst
return context
def get_queryset(self):
pass
def register(request):
form = UserRegistrationForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
email = form.cleaned_data['email']
user = User.objects.create_user(username=username, password=password, email=email)
user.save()
return redirect('/')
else:
print(form.errors)
form = UserRegistrationForm()
return redirect('/')
And in my forms.py it raises an exception error to the terminal but the form still submits.
forms.py
class UserRegistrationForm(forms.ModelForm):
email = forms.EmailField()
username = forms.CharField(max_length=25)
password = forms.CharField(widget=forms.PasswordInput)
confirm_password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = [
'username',
'email',
'password',
]
def clean(self):
email = self.cleaned_data.get('email')
current_emails = User.objects.filter(email=email)
if current_emails.exists():
raise forms.ValidationError("That email is taken")
base.html
<form method="post" enctype="multipart/form-data" action="{% url 'register' %}">{% csrf_token %}
<div class="registerBox">
<p><label for="id_username"></label> <input id="id_username" type="text" name="username" maxlength="30" placeholder="username"/></p>
<p><label for="id_email"></label> <input type="email" name="email" id="id_email" placeholder="email"/></p>
<p><label for="id_password"></label> <input type="password" name="password" id="id_password" placeholder="password"/></p>
<p><label for="id_confirm_password"></label> <input type="password" name="confirm_password" id="id_confirm_password" placeholder="confirm password"/></p>
<input type="submit" value="register" />
</div>
</form>
Any idea?
You shouldn't be trying to prevent submission when the form is invalid. What you should be doing is accepting the submission, checking the errors, then returning the errors and the filled-in form to the template.
But you are doing three things that prevent that: you are always re-instantiating the form when it is invalid, you always redirect, and you don't show errors or previous values in the template.
So you should do this:
def register(request):
form = UserRegistrationForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
email = form.cleaned_data['email']
user = User.objects.create_user(username=username, password=password, email=email)
user.save()
return redirect('/')
return render('mytemplate.html', {"form": form})
and in the template:
<div class="registerBox">
{{ form.non_field_errors }}
<p>{{ form.username.label_tag }} {{ form.username }} {{ form.username.errors }}</p>
<p>{{ form.email.label_tag }} {{ form.email }} {{ form.email.errors }}</p>
<p><label for="id_password"></label> <input type="password" name="password" id="id_password" placeholder="password"/></p>
<p><label for="id_confirm_password"></label> <input type="password" name="confirm_password" id="id_confirm_password" placeholder="confirm password"/></p>
<input type="submit" value="register" />
</div>
have you tried
if form.is_valid():
...
else:
return form_invalid(form)
You should use ajax validation if you do not want to submit invalid form.
LoginForm in forms.py
class LoginForm(forms.Form):
username = forms.CharField(label='Username', max_length=30)
password = forms.CharField(
label='Password',
widget = forms.PasswordInput(),
)
def clean_username(self):
username = self.cleaned_data['username']
try:
User.objects.get(username = username)
user.objects.get(username = username)
except ObjectDoesNotExist:
raise forms.ValidationError('Invalid Username or Password!')
def clean_password(self):
password1 = self.cleaned_data['password']
username = self.cleaned_data['username']
user = User.objects.get(username = username)
password2 = user.password
if user.check_password(password1):
return password1
else:
raise forms.ValidationError('Invalid Username or Password!')
login_page in views.py
def login_page(request):
template = get_template('login_page.html')
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return HttpResponseRedirect('/user/username')
else:
form = LoginForm()
variables = RequestContext(request, {
'form': form
})
return render_to_response('login_page.html', variables)
login_page.html template
{% extends "base.html" %}
{% block title %}User Login{% endblock %}
{% block head %}User Login{% endblock %}
{% block content %}
{% if form.has_errors %}
<p>Your username and password didn't match.
Please try again.</p>
{% endif %}
<form method="post" action=".">
<p><label for="id_username">Username:</label>
{{ form.username }}</p>
<p><label for="id_password">Password:</label>
{{ form.password }}</p>
<input type="submit" value="login" />
<input type="hidden" name="next" value="/" />
</form>
{% endblock %}
The above view when called from localhost:8000/login/ results in a User matching query does not exist error. I can't exactly sense the reason. I am using the default authentication system used by Django 1.8.
I am new to Django. Please help me out.
That exception comes from :
user = User.objects.get(username = username)
in clean_password. You already know how to fix this error, you have done it in your clean_username by sorrounding that query by try, except to avoid this error.