I am new to Django Authentication system and I am unable to find the correct debugging method.
I want to create a function to handle login requests and I have done the necessary steps to do the same.
created a login url path in main project URLS.py file.
path('members/', include('django.contrib.auth.urls')),
path('members/', include('members.urls')),
created a login url in members app to point to a function created in views.py
urlpatterns = [
path('login/', views.login_user, name='login'),]
defined what to do when user comes to specific url
def login_user(request):
if request.method == 'POST':
print('-'*100)
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
messages.success(request, ("You are now logged in"))
return redirect('index')
else:
messages.success(request, ("Invalid credentials"))
return redirect('login')
return render(request, 'registration/Login.html')
I have created a Login Page in templates folder.
{% extends 'Base.html'%}
{% block title %}
Login to the Blog Page
{% endblock %}
{% block content%}
<h1>Members Login</h1>
<div class="form-group">
<form method="POST" action="">
{% csrf_token %}
<div class="mb-3">
<label for="exampleInputEmail1" class="form-label">User Name</label>
<input type="text" class="form-control" name = "username">
<div id="emailHelp" class="form-text">We'll never share your email with
anyone else.</div>
</div>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">Password</label>
<input type="password" class="form-control" name="password">
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
<br>
</div>
{% endblock %}
Now when I get to the /members/login after submitting the user details the print statement in post method is not printed in the console. So I am suspecting that the post request is not being redirected to the login_user function. Can anyone help me out to identify why?
Djnago will fire the view that it first finds for the path members/login, and that is the login view of the django.contrib.auth module. You can swap the order of the views to visit the login view of your view:
urlpatterns = [
path('members/', include('members.urls')), # 🖘 `members.urls first
path('members/', include('django.contrib.auth.urls'))
]
But it might be better to give your view a different path, to prevent any confusion.
Related
I'm trying to set up passkeys to a testing Django website I made a while back following this guide, but at some point I get asked to "In your login view, change the authenticate call to include the request as follows":
user=authenticate(request, username=request.POST["username"],password=request.POST["password"])
However I don't have a Login view as I'm using this in my urls.py:
path("login/", userViews.LoginView.as_view(), name="login"),
I've tried to look up for guides in how to set up a login view manually but they all get me to the simplified version I'm using already.
Is there way to add that line regardless?
Otherwise, how do I create a login view manually and how should I change my login.html file?
Thanks!
Usually, we create a form in forms.py with a username and password then render this form into html template and within our view we can authenticate and then login our user.
HTML template
<body>
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
<form action="" method="post">
{% csrf_token %}
<label for="">username</label>
<input type="text" name="username" id="">
<label for="">Password</label>
<input type="password" name="password" id="">
<input type="submit" value="Login">
</form>
</body>
then handle this form in views.py file by creating loginview for it
def loginview(request):
if request.method == 'POST':
user = authenticate(request, username=request.POST["username"],
password=request.POST["password"])
if user:
login(request, user)
messages.success(request, 'Logged in successfully')
return redirect('home')
else:
messages.error(request, 'Logged in Fail')
return render(request, 'test_app/home.html')
url path
from .views import loginview
urlpatterns = [
path('', loginview, name='login'),
]
I want to know that if I am using the action in login.html <form > tag and if not using it, In both cases all is good. I am able to successfully login and if there is any error, my views.py showing the respective errors.
I think after rendering the template the django automatically send the data back to user_login function in views.py without specifying the action attribute to the <form > tag.
I just want to know that when do I need to use action attribute in the <form > tag in django template.
My urls.py
from django.urls import path
from . import views
# TEMPLATE URLS!
app_name = 'basic_app'
urlpatterns = [
path('register/', views.register, name='register'),
path('user_login/', views.user_login, name='user_login'),
]
views.py
def user_login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username, password=password)
if user:
if user.is_active:
login(request, user)
return HttpResponseRedirect(reverse('index'))
else:
return HttpResponseRedirect("ACCOUNTS NOT ACTIVE")
else:
print("Someone tried to login and failed!")
print("Username: {} and password: {}".format(username, password))
return HttpResponse("Invalid login details supplied!")
else:
return render(request, 'basic_app/login.html', {})
login.html
{% extends 'basic_app/base.html' %}
{% block body_block %}
<div class="jumbotron">
<h1>Please Login!</h1>
<form method="post" action="{% url 'basic_app:user_login' %}">
{% csrf_token %}
<label for="username">Username:</label>
<input type="text" id="username" name="username" placeholder="Enter Username">
<label for="password">Password:</label>
<input type="password" id="password" name="password" placeholder="*******">
<input type="submit" name="" value="Login">
</form>
</div>
{% endblock %}
{#action="{% url 'basic_app:user_login' %}"#}
If I am not using action="{% url 'basic_app:user_login' %}" in <form > tag of login.html, nothing changes.
#Aditya Gupta
Please look this answer first ---->>>
Now in django normaly you must define action attribut when you want the view you specified on it receive some data. It recommanded to specify url of in action attribute of form.
I am using a custom user model for my Django project and I can log in via /admin/ perfectly fine. But when I go to /accounts/login and try to log in, it just bounces me back to the login page without logging in. I am using django-registration-redux with the simple backend.
Via logging I discovered that the error happens in this method in django.contrib.auth.__init__.py:
def get_user(request):
"""
Returns the user model instance associated with the given request session.
If no user is retrieved an instance of `AnonymousUser` is returned.
"""
from .models import AnonymousUser
user = None
try:
#
# EXCEPTION THROWN ON BELOW LINE
#
user_id = _get_user_session_key(request)
backend_path = request.session[BACKEND_SESSION_KEY]
except KeyError:
pass
else:
if backend_path in settings.AUTHENTICATION_BACKENDS:
backend = load_backend(backend_path)
user = backend.get_user(user_id)
# Verify the session
if hasattr(user, 'get_session_auth_hash'):
session_hash = request.session.get(HASH_SESSION_KEY)
session_hash_verified = session_hash and constant_time_compare(
session_hash,
user.get_session_auth_hash()
)
if not session_hash_verified:
request.session.flush()
user = None
return user or AnonymousUser()
Any ideas? /accounts/register/ performs as expected, although I have overridden RegistrationView. Perhaps I have to do the same thing for logging in?
Login.html
{% extends "base.html" %}
{% load staticfiles %}
{% block body_block %}
<link href="{% static 'css/signin.css' %}" rel="stylesheet">
<div class="container">
<div class="jumbotron">
<h1 class="display-3" align="center">Login</h1>
</div>
<form method="post" action=".">
{% csrf_token %}
<h2 class="form-signin-heading">Please sign in</h2>
<label for="inputEmail" class="sr-only">Username</label>
<input type="text" name="email" id="id+username" class="form-control" placeholder="Username" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="password" id="id_password" class="form-control" placeholder="Password" required>
<button class="btn btn-lg btn-primary btn-block" type="submit" value="Submit">Login</button>
</form>
Not a member?
Register
</div>
<p>
</p>
{% endblock %}
Urls.py
class MyRegistrationView(RegistrationView):
success_url = '/'
form_class = UserProfileRegistrationForm
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form})
def register(self, form):
logging.debug("THIS IS MY REGISTER")
new_user = form.save(commit=False)
new_user.set_password(form.cleaned_data['password1'])
new_user.save()
login(self.request, new_user)
logging.debug("Logged in")
signals.user_registered.send(sender=self.__class__,
user=new_user,
request=self.request)
logging.debug("After signals")
return new_user
urlpatterns = [
url(r'^', include('base.urls')),
url(r'^admin/', admin.site.urls),
url(r'^accounts/register/$', MyRegistrationView.as_view(), name="registration_register"),
url(r'^accounts/password/change/$', MyRegistrationView.as_view(), name="auth_password_change"),
url(r'^accounts/password/change/done/$', MyRegistrationView.as_view(), name="auth_password_changed"),
url(r'^accounts/', include('registration.backends.simple.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
EDIT:
I have a temporary fix of throwing a view into login in urls.py. Something tells me this is extremely dirty but it seems to work... for now. I'm open to better alternatives.
url(r'^accounts/login/$', my_view, name="login"),
def my_view(request):
if request.POST:
username = request.POST['email']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return render(request, 'index.html', {})
# Redirect to a success page.
else:
# Return an 'invalid login' error message.
pass
else:
return render(request, 'registration/login.html', {})
Try using {{ form }} in your login template, instead of rendering the fields manually. This can show whether the problem is in your template or elsewhere.
In this case, I think that the form fields should be username and password, not email and password as you have.
<input type="text" name="username" id="id_username" class="form-control" placeholder="Username" required autofocus>
<input type="password" name="password" id="id_password" class="form-control" placeholder="Password" required>
I have created two different types of users - truck & company. Here is my registration page for a user
After registering, the data about whether the user is a truck or company will go to the database.
In my login page,
only Email and Password are to be entered. In my custom user creation form, I added the field username = email.
When I am trying to login with valid credentials, the page is not redirecting me to a particular page according to the user-type. Instead, an error which I created for invalid credentials in login.html is raising - "Your email and password didn't match. Please try again."
here's my code:
views.py:
def login_view(request):
title = "Login"
if request.method == 'POST':
form = LoginForm(data=request.POST)
email = request.POST.get('email', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=email, password=password)
if form.is_valid():
auth.login(request, user)
user_type = form.cleaned_data['Label']
if user.is_active & user_type == 'Truck':
return HttpResponseRedirect('/post_load/')
elif user_type == 'Company':
return HttpResponseRedirect('/live_deal/')
else:
form = LoginForm()
return render(request, 'registration/login.html', {'form' : form, 'title': title})
urls.py:
# url(r'^login/$', views.login_view),
# url(r'^accounts/login/$', views.login_view),
url(r'^login/$', 'django.contrib.auth.views.login', {'authentication_form': LoginForm}),
url(r'^accounts/login/$', 'django.contrib.auth.views.login', {'authentication_form': LoginForm}),
forms.py:
class LoginForm(auth.forms.AuthenticationForm):
email = forms.EmailField(label=_("Email"),widget=forms.EmailInput)
CHOICES= (('Truck', 'Truck'),('Company', 'Company'),)
Label = forms.ChoiceField(choices=CHOICES, label='Label', widget=forms.RadioSelect())
login.html:
{%extends "registration/header.html"%}
{% block content %}
{% if form.errors %}
<p>Your email and password didn't match. Please try again.</p>
{% endif %}
<form class="form-horizontal" method="post" action = "." >{%csrf_token%}
<div class="panel panel-default login">
<div class="panel-heading">
<span class="glyphicon glyphicon-lock"></span> Login</div>
<div class="panel-body">
<form class="form-horizontal" role="form">
<div class="form-group">
<div class='col-sm-6 col-sm-offset-4'>
<table border="0">
<div class="col-sm-4">
<tr><th><label for="id_user" class="col-sm-4 control-label">Email:</label></th><td>{{ form.email }}</td></tr> </div>
<div class="col-sm-4">
<tr><th><label for="id_password" class="col-sm-4 control-label">Password:</label></th><td>{{ form.password }}</td></tr> </div>
</table> </div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-8">
<div class="checkbox">
<label>
<input type="checkbox"/>
Remember me
</label>
</div>
</div>
</div>
<div class="form-group last">
<div class="col-sm-offset-4 col-sm-8">
<button type="submit" class="btn btn-success btn-sm">
Sign in</button>
<input type="hidden" name="next" value="/" />
<label class="col-sm-offset-3">
Forget Password?
</label>
</div>
</div>
</form>
</div>
<div class="panel-footer">
Not Registered? Register</div>
</div>
</form>
{% endblock %}
{% if form.errors %}
<p>Your email and password didn't match. Please try again.</p>
This error is rather broad. You could loop through it to see the actual errors.
Better yet; don't use your own authentication system just use Django's built-in system which also allows you to add extra fields to the user model.
Example:
from django.contrib.auth import authenticate, login
def my_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
# Redirect to a success page.
else:
# Return a 'disabled account' error message
...
else:
# Return an 'invalid login' error message.
...
Note, you don't need to write your own login view, you can also use Django's login system to handle the form, pass reset/change, urls and templates (which you can override with your own template):
urls:
urlpatterns = [
url('^', include('django.contrib.auth.urls')),
]
Then /login/ will be your login page.
After it works with the Django contrib auth module, extend it with your own custom HTML login form.
django.contrib.auth.views
I'm new to the django login setup.
And I've researched my way to something that seemed good and copied that.
I have discovered this decorator:
#user_passes_test
That helps me make sure people with the right access to my "/dashboard" page have logged in.
After getting redirected to login the url is:
placeholder.it/login/?next=/dashboard/%3Fcvr%3D24256790
BUT the user always get send to:
placeholder.it/accounts/loggedin
insted of the next url.
How come??
This is some of my code:
views.py
#user_passes_test(lambda u:u.is_staff, login_url='/accounts/login/')
def dashboard(request):
cvr = request.GET.get('cvr', '')
return render(request,'dashboard.html', { "cvr": cvr})
def login(request):
c = {}
c.update(csrf(request))
return render_to_response('login.html', c)
def auth_view(request):
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
return HttpResponseRedirect('/accounts/loggedin')
else:
return HttpResponseRedirect('/accounts/invalid')
login.html
{% extends "base.html" %}
{% block content %}
{% if form.errors %}
<p class="error">Sorry, that's not a valid username or password</p>
{% endif %}
<form action="{% url 'auth' %}" method="post">{% csrf_token %}
<label for="username">User name:</label>
<input type="text" name="username" value="" id="username">
<label for="password">Password:</label>
<input type="password" name="password" value="" id="password">
<input type="submit" value="login" />
</form>
<br>
Login to access all sites
{% endblock %}
urls.py
url(r'^accounts/login/$', views.login, name='login'),
url(r'^accounts/auth/$', views.auth_view, name='auth'),
url(r'^dashboard/$', views.dashboard, name='dashboard'),
Appreciate any help <3
Your decorator is sending the users who are not logged in to the login view. The login page has a form that posts to the auth_view view. The auth view explicitly redirects every logged in user to /accounts/loggedin.
You're redirecting users on your own, through the codes in auth_view. Your code doesn't respect the next query parameter (that the decorator is appending to the login url). Your code should read the value of the next parameter and put it in a hidden field inside the form. On the POST request to auth_view, you should read that value and redirect the user to that url.
There is an inbuilt decorator to handle if user has logged in or not
Import the following
from django.contrib.auth.decorators import login_required
And place the decorator above your function:
#login_required(redirect_field_name='next')
def page(request):
Add this to your login template
input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}"