I'm trying to write a simple app that let users to login, in Django. I've downloaded a pretty bootstrap login template, but I can't hook it up to my Django project. When I click submit, nothing happens, Here's the view:
def login_view2(request):
if request.method == 'POST':
print("POST METHOD")
form = LoginForm(request.POST)
if form.is_valid():
print("FORM VALID")
uname = form.cleaned_data['username']
pword = form.cleaned_data['password']
user = authenticate(username=uname, password=pword)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect('/')
else:
print("The account has been disabled!")
else:
print("The username and password were incorrect!")
else:
print("LOGIN FORM SHOWN")
form = LoginForm()
return render(request, 'login2.html', {'form': form})
and here's the form
<form id="login-form" action="login2/" method="post">
{% csrf_token %}
<div class="modal-body">
<div id="div-login-msg">
<div id="icon-login-msg" class="glyphicon glyphicon-chevron-right"></div>
<span id="text-login-msg">Type your username and password.</span>
</div>
<input id="login_username" class="form-control" type="text" placeholder="Username" required>
<input id="login_password" class="form-control" type="password" placeholder="Password" required>
</div>
<div class="modal-footer">
<div>
<input type="submit">Login</input>
</div>
</div>
</form>
Thank you very much in advance!
You haven't given your HTML fields a name attribute, so the browser can't send any data to the server.
Also you need to display errors for when the form is not valid, using {{ form.errors }}.
Related
When trying to create a simple web page with login and sign up i ran into the issue of django not recognzing the created user. In views.py i created a simple message that displays "Incorrect password or email" if user does not exist. I created a user and made sure that the password was correct when i inputed it into the login form however it still gave me the message of "Incorrect password or email". Instead of redirecting to home like a created user should it errored and i could not figure out why it is not accepting the password/email in the form.
views.py
from django.shortcuts import redirect, render
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
from django.contrib.auth.models import User
def home(request):
return render(request, 'home.html')
def signup(request):
if request.method == "POST":
email = request.POST['email']
password = request.POST['password']
myuser = User(email=email)
myuser.set_password(password)
myuser.save()
messages.success(request, "Your account has been successfully created ")
return redirect('signin')
return render(request, 'signup.html')
def signin(request):
if request.method == "POST":
email = request.POST['email']
password = request.POST['password']
user = authenticate(request, email = email, password = password)
if user is not None:
login(request, user)
email = user.email
messages.success(request, "Successfully Logged In")
return redirect ('home')
else:
messages.info(request, "Email or Password is Incorrect")
return render(request, 'signin.html')
return render(request, 'signin.html')
def signout(request):
pass
urls.py
from django.urls import path
from . import views
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns = [
path('', views.home, name = "home"),
path('signin', views.signin, name = "signin"),
path('signup', views.signup, name = "signup"),
]
urlpatterns += staticfiles_urlpatterns()
signup.html
<h1>Sign up</h1>
<form action = "/signup" method = "POST">
{% csrf_token %}
<div class="mb-3">
<label for="exampleInputEmail1" class="form-label">Email address</label>
<input type="email" class="form-control" id="email" name = "email" aria-describedby="emailHelp" placeholder = "example#example.com">
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name = "password">
</div>
<button type="submit" class="btn btn-primary">Sign up</button>
</form>
signin.html (login page)
<h1>Login</h1>
{%if messages%}
{%for message in messages%}
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<strong>Hey,</strong> {{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
{% endif %}
<form action = "/signin" method = "POST">
{% csrf_token %}
<div class="row mb-3">
<label for="inputEmail3" class="col-sm-2 col-form-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="email" name = "email">
</div>
</div>
<div class="row mb-3">
<label for="inputPassword3" class="col-sm-2 col-form-label">Password</label>
<div class="col-sm-10">
<input type="password" class="form-control" id = "password" name = "password">
</div>
<div class="col-sm-10">
</div>
<button type="submit" class="btn btn-primary">Sign in</button>
</form>
What is the status of your user. An inactive user is one that has its is_active field set to False. The default backend ModelBackend and RemoteUserBackend prohibits the inactive users from authenticating. You didn't specify user status. So please check the user status also.
You can improve this part as following:
myuser = User(email=email, is_active=True)
myuser.set_password(password)
myuser.save()
To set password you have to use set_password function.
If user do successfull login then it is redirecting to next but if user can not do login then I wants to change template and wants to redirect to next page but it is not working.
Views.py
def login(request, template_path='login.html'):
"""
"""
# We'll only allow staff to view this page after login.
if request.user.is_authenticated:
return redirect('home')
if request.method == 'POST':
if request.META['HTTP_REFERER'].split('/')[-1] == 'bs5':
template_path = 'theme/bs5_theme.html'
response = LoginView.as_view(
template_name=template_path,
redirect_field_name='next',
form_class=EmailAuthenticationForm,
)(request)
if request.is_ajax():
if request.user.is_authenticated:
return HttpResponse(
json.dumps(dict(success=True, next=request.POST.get("next"))),
content_type="application/json"
)
return HttpResponse(json.dumps(False), content_type="application/json")
else:
return response
else:
form = auth_forms.AuthenticationForm()
model = dict(login_form=form)
return render(request, template_path, model)
login.html
{% if form.non_field_errors %}
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
Login failed. Email and password case-sensitive.
</div>
{% endif %}
<form id="formLogin" action="{% url 'login' %}" method="post" role="form">
<input type="hidden" name="csrfmiddlewaretoken">
<input type="hidden" name="next" value="/bs5" />
<label for="id_username" class="form-label">Email address</label>
<input type="username" class="form-control" id="id_username" name="username" value="{{ form.username.value }}">
<label for="id_password" class="form-label">Password</label>
<input type="password" class="form-control" id="id_password" name="password">
<button class="btn btn-primary btn-lg" type="submit">Log In</button>
</form>
I have also try with
return HttpResponseRedirect('/bs5')
But then it is not showing login error.
Any help would be appreciated.
In case you want to redirect a user who couldn't log in to a different page, one of the ways that you may do it is:
from django.contrib import messages
from django.contrib.auth import authenticate, login
from django.shortcuts import redirect
def login(request, template_path='login.html'):
if request.user.is_authenticated:
redirect('home')
user = authenticate(request, username= request.POST.get('username'), password=request.POST.get('password'))
if user is not None:
next_url = request.POST.get('next') # get your next url
messages.error(request, _('Invalid credentials')) # display login error on the next page
return redirect(next_url)
else:
login(request, user)
# redirect to the successful url that you wish to
For more information on displaying messages in your template, you may consult django's documentation
When a new user signs up for an account, the admin panel shows that a password has not been set for the user (despite saving it via views.py). Another strange thing I noticed is that the password is being saved to the email field in the database. The code appears fine. Not sure where I went wrong. Any help would be greatly appreciated.
sign up html template
{% if user.is_authenticated %}
<h2>currently logged in as {{ user.username }} </h2>
{% else %}
<h1 class="h5 text-center">Create Account</h1>
<h4>{{ error }}</h4>
<form method="POST">
{% csrf_token %}
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" name="username" autocomplete="username" placeholder="Username" id="id_username" required>
</div>
<div class="form-group">
<label for="password1">Password</label>
<input type="password" class="form-control" name="password1" placeholder="Password" autocomplete="new-password" required id="id_password1">
<small>Password must be at least 8 characters</small>
</div>
<div class="form-group">
<label for="password2">Confirm Password</label>
<input type="password" class="form-control" name="password2" placeholder="Confirm Password" autocomplete="new-password" required id="id_password2">
</div>
<ul>
<li>Your password can’t be too similar to your other personal information.</li>
<li>Your password must contain at least 8 characters.</li>
<li>Your password can’t be a commonly used password.</li>
<li>Your password can’t be entirely numeric.</li>
</ul>
<!-- <div class="form-group">
<div class="custom-control custom-checkbox text-small">
<input type="checkbox" class="custom-control-input" id="sign-up-agree">
<label class="custom-control-label" for="sign-up-agree">I agree to the <a target="_blank" href="utility-legal-terms.html">Terms & Conditions</a>
</label>
</div>
</div> -->
<button class="btn btn-primary btn-block" type="submit">Create Account</button>
</form>
views.py
def signup(request):
if request.method == 'GET':
return render(request, 'events/signup.html', {'form': UserCreationForm()})
else:
# Create new user and profile
if request.POST['password1'] == request.POST['password2']:
try:
print(request.POST['password1'])
print(request.POST['password2'])
user = User.objects.create_user(request.POST['username'], request.POST['password1'])
user.save()
login(request, user)
return redirect('home')
except IntegrityError:
return render(request, 'events/signup.html', {'form': UserCreationForm(), 'error':'Username has already been taken. Please use a different name.'})
else:
# Tell the user the passwords don't match
return render(request, 'events/signup.html', {'form': UserCreationForm(), 'error':'Passwords did not match'})
There's no mention of "email" anywhere in the code but for some reason the password gets saved as email and the actual password isn't getting set.
You need to set password explicitly, or send it in the third param, second param of create_user method is email, thats why password is being set as email.
reference to set_password method
reference to create_user method
You need something like this.
user = User.objects.create_user(username=request.POST['username'])
user.set_password('new password')
user.save()
Your code:
user = User.objects.create_user(request.POST['username'], request.POST['password1'])
user.save()
See the the docs:
create_user(username, email=None, password=None, **extra_fields)
So, oops, you send the password as second argument and it is interpreted as being the email address.
create_user(username=request.POST['username'], password=request.POST['password1'])
Should work.
I have a very common problem - after login I want to redirect to the page where login was called. I can describe situation exactly like here: Django: Redirect to previous page after login
There are 2 options where you can log in - from the home page (which is defined in base.html) and from bokeh.html (other views inherit from bokeh)
my base.html and bokeh.html have the same block to redirect to login. Difference is, that login called from home page should return to home page and from other page should return to page where was called.
<li class="nav-item">
<a class="nav-link" href="{% url 'login' %}">Login</a>
</li>
my login.html
<form method="POST">
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control" placeholder="Enter Username" name="username" required>
</div>
<div class="form-group">
<input type="password" class="form-control" placeholder="Enter Password" name="password" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-dark">Login</button>
</div>
</form>
and views.py
def login(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username,password=password)
if user is not None:
auth.login(request,user)
return redirect('home')
else:
messages.info(request,'Invalid credentials')
return redirect('login')
else:
return render(request,'login.html')
I was trying to add next to my form in login.html but it didn't work. While accessing to login from page other than home page it was like: localhost:8000/login?next=/bokeh/ and after submiting form I was still on login but URL changed to localhost:8000/login?next=. I know it's pretty hard to explain but I will add another information in need.
First, change the template to include the urlencoded next parameter to the login url:
<li class="nav-item">
<a class="nav-link" href="{% url 'login' %}?next={{ request.path |urlencode }}">Login</a>
</li>
Second, your login template needs to preserve the value of next:
<form method="POST">
<input type="hidden" name="next" value=""{{ next }}">
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control" placeholder="Enter Username" name="username" required>
</div>
<div class="form-group">
<input type="password" class="form-control" placeholder="Enter Password" name="password" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-dark">Login</button>
</div>
</form>
Third, your login view should retrieve the URL parameter and pass it to the template:
from django.conf import settings
def login(request):
if request.method == 'GET':
next = request.GET.get('next', settings.LOGIN_REDIRECT_URL)
return render(request, 'login.html', {'next': next})
if request.method == 'POST':
next = request.POST['next']
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username,password=password)
if user is not None:
auth.login(request,user)
return redirect(next)
else:
messages.info(request,'Invalid credentials')
return redirect('login')
Finally, you should consider using the Django Authentication Views instead of writing your own login views!
I'm trying to create custom authentication in Django where the identifier is an email, there is a required field called name and a password field. The login view works fine, but I get an error username from the forms.
Here is my views.py
def auth_login(request):
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
user = authenticate(email=email, password=password)
if user is not None:
login(request, user)
return HttpResponseRedirect("/tasks/")
else:
return HttpResponse('Invalid login.')
else:
form = UserCreationForm()
return render(request, "registration/login.html", {
'form': form,
})
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
new_user = authenticate(email=request.POST['email'], password=request.POST['password1'])
login(request, new_user)
return HttpResponseRedirect("/tasks/")
else:
form = UserCreationForm()
return render(request, "registration/register.html", {
'form': form,
})
Here is my register.html
<form class="form-signin" role="form" method="post" action="">
{% csrf_token %}
<h2 class="form-signin-heading">Create an account</h2>
<input type="text" name="name" maxlength="30" class="form-control" placeholder="Username" required autofocus>
<br>
<input type="email" name="email" class="form-control" placeholder="Email" required>
<br>
<input type="password" name="password1" maxlength="4096" class="form-control" placeholder="Password" required>
<br>
<input type="password" name="password2" maxlength="4096" class="form-control" placeholder="Password confirmation" required>
<input type="hidden" name="next" value="/tasks/" />
<br>
<button class="btn btn-lg btn-primary btn-block" type="submit">Create the account</button>
</form>
{% if form.errors %}
{% for error in form.errors %}
{{ error }}
{% endfor %}
{% endif %}
This prints the error username. What's wrong here?
You'll need to create your own form instead of using django's own UserCreationForm. Django's form requires you to have a username.
You don't have a username, so Django's form will not work for you. So... create your own. See also Django 1.5: UserCreationForm & Custom Auth Model, and especially the answer https://stackoverflow.com/a/16570743/27401 .