I am using the DJango login/authentication functionality. I have extended it with a Profile using the Extending The Existing User Model approach.
In the "Profile" is a variable called restrole. In the code below, restrole is being used to control the NEXT screen the user sees (as well as as the data on it):
def user_login(request):
if request.method == 'POST':
# First get the username and password supplied
username = request.POST.get('username')
password = request.POST.get('password')
# Django's built-in authentication function:
user = authenticate(username=username, password=password)
if user:
# Check it the account is active
if user.is_active:
# Log the user in.
login(request, user)
myprofile = user.userprofileinfo
restrole = myprofile.restrole
if restrole == 1:
return HttpResponseRedirect(reverse('authinduction:induct-owner'))
elif restrole == 2:
return HttpResponseRedirect(reverse('authinduction:induct-office'))
elif restrole == 3:
return HttpResponseRedirect(reverse('authinduction:induct-customer'))
elif restrole == 4:
return HttpResponseRedirect(reverse('authinduction:induct-field-work'))
else:
return HttpResponse("Unrecognized Role")
This Part works fine
I can get data from the "request" variable
# First get the username and password supplied
username = request.POST.get('username') <<< data is returned
password = request.POST.get('password') <<< data is returned
The problem
When I execute one of the branches:
if restrole == 1:
return HttpResponseRedirect(reverse('authinduction:induct-owner'))
It goes to the correct function, but "request" does not appear to have any data associated with it. Getting the "username" results in getting a value of "None"
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from authinduction.models import Mstrauthownerrdx
from django.contrib.auth.models import User
def inductowner(request):
username = request.POST.get('username') <<< does NOT work, returns "None"
user = User.objects.get(username=username) <<< causes a DoNotExist error here
What is the best way to come around this problem?
TIA
Update
#Alasdair - Thanks for the response. That did the trick! I noticed that the form itself accesses the user login info as follows:
<input type="text" name="username" placeholder="Enter Your Logon Info">
As metioned above, to get the username (when doing the POST as you have noted), one does
username = request.POST.get('username')
In all of this, I keep seeing "username", but - to solve the problem, one users "request.user". Why is this the case? I ask because I would have never thought to use "request.user" to get the information. If anything, I would have used "request.username"
When you return a redirect response, Django does a GET request to that URL, so the POST data is not sent to the new URL.
Since you have already logged-in the user in user_login, I would fetch the user from the request in the next view.
from django.contrib.auth.decorators import login_required
#login_required
def inductowner(request):
user = request.user
...
The login_required ensures that only logged-in users can access the view, so stops anonymous users going straight to the inductowner view.
Related
I'm working on a django application. The application has a dashboard. How can i make it so that everytime the user wants to access the dashboard, he/she has to confirm their identity, with the same password they use to log into the same application?
Thank you
#Verify that the USERNAME and PASSWORD combination exist USING THE AUTHENTICATE METHOD,
Views.py:
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
#IN YOUR CASE get the pwd using forms or something,
instance_password = request.post.get('the_pwd_field')
user = authenticate(request, username= request.user.username, password= instance_password)
if user is not None:
# REDIRECT TO THE DASHBOARD
else:
# FAIL CASE SCENARIO
In views.py
from django.contrib.auth.hashers import check_password
form = YourFormForPassword(request.POST or None)
if form.is_valid():
currentpasswordentered = form.cleaned_data.get("try_password")
currentpassword = request.user.password
authenticate_user = check_password(currentpasswordentered, currentpassword)
if authenticate_user:
# REDIRECT TO THE DASHBOARD
else:
#Redirect to other page or keep same login page
If you want, user to enter credentials explicitly before accessing the dashboard, then you have to return the "form" that accepts creds from user, when they try to access the dashboard.
def dashboard_login_view(request):
context = {}
if request.method == 'POST':
form = DashboardLoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('dashboard_login_username').lower()
password = form.cleaned_data.get('dashboard_login_password')
authenticated = check_password(password)
if authenticated:
return HttpResponseRedirect(reverse('dashboard_view'))
else:
messages.error('User is not authenticated.')
return HttpResponseRedirect(reverse('login'))
else:
context['form_one'] = DashboardLoginForm()
return render(request, 'dashboardlogin.html', context)
I'm trying to build a login page in Django. But whenever I try to authenticate the user it doesn't work. The user passes each time even if the user doesn't exist. Any help I would really appreciate it!
def login(request):
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
form = CreateUserForm()
return render(request,
"leadfinderapp/login.html",
context={"form":form})
The user isn't actually getting authenticated, you just aren't handling errors in the form. The function is just rendering the "leadfinderapp/login.html" template again regardless of the user's data entered.
To handle errors in the form, you need to have a
if form.is_valid():
# submit information and login
else:
# re render form with errors
You should look into using Django All Auth to handle your authentication (https://django-allauth.readthedocs.io/en/latest/installation.html) it's customizable but handles a lot of the work for you - just like Django itself!
I am using django registration redux for login and auth purposes. I want to do the following.
if the user logs in for the first time i want to redirect to URL-"profile/create"
if the user is a returning user i dont want the user to access the URL-"profile/create" and i want the user to be redirected to another URL.
django-registration-redux seems to use Django's login-view for logging users in per default.
Thus I would provide a customized login view instead that additionally inspects the user that tries to log in and checks if last_login is already filled out.
Depending on the result the user then can be redirected to the desired page once the authentication succeeded.
in most basic form when user login first time it has to be registered.
do not use this kind of functionality at login use it at register function (view)
this is a old draft code that give you the idea
def ragister(request):
if request.user.is_authenticated:
return HttpResponseRedirect('/profile-settings/')
if request.method == 'POST':
fname = request.POST['fname']
lname = request.POST['lname']
username = request.POST['username']
password = request.POST['password']
users = User()
users.password = password
users.username = username
users.first_name = fname
users.last_name = lname
try:
users.set_password(password)
users.save()
users = authenticate(username=username, password=password)
if users is not None:
login(request,users)
return HttpResponseRedirect('/profile-settings/')
messages.success(request, "This number is registered please try other number or reset your password")
return HttpResponseRedirect('/register/')
I've read a lot topics about this problem but still can't fix problem.
I am going by Tango With Django tutorial (part 9) and get strange problem.
When I create user, I can't then get user object using authenticate method.
GitHub project: (link)
This is my register function from views:
def register(request):
# A boolean value for telling the template whether the registration was
# successful.
# Set to False initially. Code changes value to True when registration
# succeeds.
registered = False
# If it's a HTTP POST, we're interested in processing form data.
if request.method == 'POST':
# Attempt to grab information from the raw form information
# Note that we make use of both UserForm and UserProfileForm
user_form = UserForm(data=request.POST)
profile_form = UserProfileForm(data=request.POST)
# If the two forms are valid...
if user_form.is_valid() and profile_form.is_valid():
# Save the user's form data to the database.
user = user_form.save()
# Now we hash the password with the set_password method.
# Once hashed, we can update the user object
user.set_password(user.set_password)
user.save()
# Now sort out the UserProfile instance.
# Since we need to set the user attribute ourselves, we set
# commit=False
# This delays saving the model until we're ready to avoid
# integrity problems.
profile = profile_form.save(commit=False)
profile.user = user
# Did the user provide a profile picture?
# If so, we need to get it from the input form and put it in the
# UserProfile
if 'picture' in request.FILES:
profile.picture = request.FILES['picture']
# Now we save the UserProfile model instance
profile.save()
# Update our variable to tell the template registration was
# successful
registered = True
# Invalid form or forms - mistakes or something else?
# Print problems to the terminal.
# They'll also shown to the user
else:
print user_form.errors, profile_form.errors
# Not a HTTP POST, so we render out form using two ModelForm instances.
# These forms will be blank, ready for user input.
else:
user_form = UserForm()
profile_form = UserProfileForm()
context_dict = {
'user_form': user_form,
'profile_form': profile_form,
'registered': registered
}
# Render the template depending on the context.
return render(request, 'rango/register.html', context_dict)
user_login function from views:
def user_login(request):
# If the request is a HTTP POST, try to pull out the relevant information
if request.method == 'POST':
# Gather the username and password provided by the user.
# This information is obtained from the login form.
# We use request.POST.get('<variable>') as opposed to
# request.POST['variable'], because the
# request.POST.get('<variables>') return None, if the value does not
# exist, while the request.POST['<variable>'] will raise
# key error exception
username = request.POST.get('username')
password = request.POST.get('password')
# Use Django's machinery to attempt to see if the username/password
# combination is valid - a User object is returned if it is.
user = authenticate(username=username, password=password)
# user = User.objects.get(username='user1')
print user
# If we have a User object, the details are correct.
# If None (Python's way of representing the absence of a value), no
# user with matching credentials was found.
if user:
# Is the account active? It could have been disabled
if user.is_active:
# If the account is valid and active, we can log the user in.
# We'll send the user back to the homepage
login(request, user)
return redirect('rango:index')
else:
# An inactive account was user - no logging in
return HttpResponse("Your Rango account is disabled.")
else:
# Bad login details were provided. So we can't log the user in.
print "Invalid login details: {0}, {1}".format(username, password)
return HttpResponse("Invalid login details supplied")
# The request is not a HTTP POST, so display the login form.
# This scenario would most likely be a HTTP GET.
else:
# No context variables to pass to the template system, hence
# the blank dictionary object..
return render(request, 'rango/login.html')
This is the code in Tango with django
user.set_password(user.password)
user.save()
And your's is
user.set_password(user.set_password)
user.save()
Try to replace set_password with password.
My problem in the short version:
I have added the login_required decorator to one of my views. If I enter the URL in the browser which executes this view, the browser correctly redirects to the URL that contains my login form if the user is not authenticated. However, the browser never redirects back to the previous page and I have no idea why this does not work. I have tried hundreds of things.
My problem in the long version:
I have a Django project with a single app, let's call it my_app. All the templates of my project reside in templates/my_app/. I have a template called main.html which contains several forms, among them my login form. With an additional POST parameter called form-type, I check which of the forms has been submitted. The code looks like this:
def process_main_page_forms(request):
if request.method == 'POST':
if request.POST['form-type'] == u'login-form':
template_context = _log_user_in(request)
elif request.POST['form-type'] == u'registration-form':
template_context = _register_user(request)
elif request.POST['form-type'] == u'password-recovery-form':
template_context = _recover_password(request)
else:
template_context = {
'auth_form': AuthenticationForm(),
'registration_form': RegistrationForm(),
'password_recovery_form': EmailBaseForm()
}
return render(request, 'my_app/main.html', template_context)
The function _log_user_in() looks like this:
def _log_user_in(request):
message = ''
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)
else:
message = 'Your account has been disabled. ' \
'Please contact the administrator.'
else:
message = 'Your username and password didn\'t match. Please try again.'
template_context = {
'auth_form': AuthenticationForm(),
'registration_form': RegistrationForm(),
'password_recovery_form': EmailBaseForm(),
'message': message,
}
return template_context
I also include the necessary <input> elements in the template, e.g. for the login form this is:
<input type="hidden" name="form-type" value="login-form" />
<input type="hidden" name="next" value="{{ next }}" />
The URL pattern for this view is:
url(r'^$', process_main_page_forms, name='main-page')
My second view renders two forms for changing email address and password for an authenticated user. It looks like this:
#login_required(login_url='/')
def change_user_credentials(request):
if request.method == 'POST':
if request.POST['form-type'] == u'change-email-form':
template_context = _change_email_address(request)
elif request.POST['form-type'] == u'change-password-form':
template_context = _change_password(request)
else:
template_context = {'change_email_form': ChangeEmailForm()}
return render(request, 'my_app/user.html', template_context)
The URL pattern for this second view is:
url(r'^account/$', change_user_credentials, name='user-page')
Whenever I access /account/ when I'm not authenticated, I'm successfully redirected to the main page that contains the login form. The resulting URL is http://127.0.0.1:8000/?next=/account/ that contains the necessary next parameter. However, when I log in my account, I'm still on the main page. I never get redirected to the user page, although I provided the necessary next parameter in the login form. It seems that this parameter is always empty, but I don't know why. I also don't have any other redirection calls in my code.
Can you help me solving this problem? Thank you very much in advance.
Possibly a trite answer, but the reason that no redirect is happening is because you don't seem to be doing anything with the next query parameter.
In fact, in the event that a user logs in successfully, you show the same page (albeit with a different context dictionary) as if they attempted to do something else:
def process_main_page_forms(request):
if request.method == 'POST':
if request.POST['form-type'] == u'login-form':
template_context = _log_user_in(request)
...
...
return render(request, 'my_app/main.html', template_context)
As the Django docs explain, it's the contrib.auth.views.login() function that processes the next parameter, and you're not using that view (although you are using the confusingly-identically-named contrib.auth.login function).
You should either just use the included view (which, in addition to processing next, also checks for is_active), or add the redirect functionality to your view, in which case it's probably worth bringing the authentication code into process_main_page_forms() unless you're sure you'll need _log_user_in() elsewhere:
from django.http import HttpResponseRedirect
from django.conf import settings
def process_main_page_forms(request):
if request.method == 'POST':
if request.POST['form-type'] == u'login-form':
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)
if request.GET.get('next', False):
return HttpResponseRedirect(request.GET.get('next'))
else:
return HttpResponseRedirect(settings.LOGIN_REDIRECT_URL)
else:
message = 'Your account has been disabled.'
else:
message = 'Your username and password didn\'t match. Please try again.'
# If we've reached this point then the login failed
template_context = {
'auth_form': AuthenticationForm(),
'registration_form': RegistrationForm(),
'password_recovery_form': EmailBaseForm(),
'message': message,
}
elif ...:
# Do things with other form types
else:
return render(request, 'my_app/main.html', template_context)
The example usage of contrib.auth.login has the following:
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.
Your code is almost there, but you were missing the "redirect to a success page" part, which is where next would come into play.