How to get logged in username in views.py in django - python

Actually i'am very new to django and python. In /templates/home.html, added {{ user.username }} it's showing currently logged in username
<p>Welcome {{ user.username }} !!!</p>
I want to get currently logged in username in views.py file. How to get username?
i tried different way but i am not get the result
user = User.objects.get(username=request.user.username)
username = request.GET['username']
def sample_view(request):
current_user = request.user
print(current_user)
Please tell me, How to achieve my result.
my views.py look like this. is there any problem on my views.py
#!python
#log/views.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.template import Context
from contextlib import contextmanager
# Create your views here.
# this login required decorator is to not allow to any
# view without authenticating
#login_required(login_url="login/")
def home(request):
return render(request,"home.html")
#dummy_user = {{ username }}
#user = User.objects.get(username=request.user.username)
#username = request.GET['username']
#print(usernam
#user = request.user
#print(user)
def sample_view(request):
current_user = {}
#current_user['loggeduser'] = request.user
#or
current_user['loggeduser'] = request.user.username
return render(request,"home.html",current_user)
# print(current_user.id)

Provided that you have enabled the authentication middleware, you don't need to do any of this. The fact that the username shows up in your template indicates that you have enabled it. Each view has access to a request.user that is an instance of a User model. So the following is very much redundant
user = User.objects.get(username=request.user.username)
Because you already have request.user.username!! if you wanted to find the user's email, you do request.user.email Or just do
user = request.user
and use the newly created variable (eg user.username)
Reference: https://docs.djangoproject.com/en/1.10/ref/request-response/#django.http.HttpRequest.user
From the AuthenticationMiddleware: An instance of AUTH_USER_MODEL
representing the currently logged-in user. If the user isn’t currently
logged in, user will be set to an instance of AnonymousUser. You can
tell them apart with is_authenticated, like so:

Related

How to check django staff user first time login in admin panel?

I am working on a django project and I am using the default auth app for authentication.
I know that there is a last_login field in user model which stores the user's last login time.
When a staff user logs in first time into the admin panel, I want to check if last_login field is none & redirect him to the change password page.
Where should I put this check?
What I have tried so far:
I have tried to use a custom login form and override the default confirm_login_allowed method on it, but it seems like I can only raise a validation error to block login attempt using these.
I also tried using django.contrib.auth.signals.user_logged_in Signal but that also does not allow me to return a redirect response when last_login is None.
I want to know how I can return a redirect response after the user has been authenticated.
Customise Django admin using AdminSite and use login_form attribute to give the custom login form for the Admin login page.
admin.py
class MyAdminSite(AdminSite):
login_form = CustomAdminLoginForm
admin_site = MyAdminSite(name='myadmin')
admin_site.register(User)
admin_site.register(Group
urls.py
When overriding the Admin we have to get rid of Django default admin
from app.admin import admin_site
url(r'^admin/', admin_site.urls)
forms.py
AuthenticationForm have the confirm_login_allowed method use this to grant permission to login in or not login in.
class CustomAdminLoginForm(AuthenticationForm):
def confirm_login_allowed(self, user):
if user.last_login:
raise ValidationError(mark_safe('Hey first time user please reset your password here... test'), code='inactive')
Note: There is lot of edge cases you have to consider for this approach.
What if user not set the password in the first time and how you're going to handle second attempt..? This time last_long not None. Although date_joined comes rescue. last_login == date_joined
But What if the user not set the password in first day and comes next day ?
Edit:
You can use signal to check the logged in user and apply the config_login_allowed logic here...?
from django.contrib.auth.signals import user_logged_in
def change_password_first_time(sender, user, request, **kwargs):
# Your business logic here...
user_logged_in.connect(change_password_first_time)
Django admin is not that configurable. You should hook into its internal views. Login/logout views are inside Django AdminSite class (the one you usually access by admin.site). My implementation is a bit hacky but small:
Paste at the top of urls.py
from django.contrib import admin
from django.contrib.admin import AdminSite
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
class MyAdminSite(AdminSite):
def login(self, request, extra_context=None):
new_user = False
user = None
username = request.POST.get('username') # Hack to find user before its last_login set to now.
if username:
user = User.objects.filter(username=username).first()
if user:
new_user = user.last_login is None
r = super(MyAdminSite, self).login(request, extra_context)
if new_user and request.user == user and isinstance(r, HttpResponseRedirect): # Successful logins will result in a redirect.
return HttpResponseRedirect(reverse('admin:password_change'))
return r
admin.site = MyAdminSite()
If you want a cleaner solution I suggest to use a boolean inside user model instead of relying on last_login so you could just check request.user instead of my hack into request.POST.
You could read AdminSite.login and django.contrib.auth.views.login to see what is actually happening inside Django.
It was a big problem for me at once. I found a way to do it easy. Create a different variable to save the value of the users logged in data, when user is trying to login.
Below is my code:
if user.last_login is None:
auth.login(request,user)
return redirect(alertPassword)
# when user is login for the first time it will pass a value
else:
auth.login(request,user)
return redirect(moveToLogin)
def moveToLogin(request):
return render(request,"home.html")
def alertPassword(request):
first_login=True
return render(request,"home.html",{"first_login":first_login})
#it will pass a value to the template called first login is True
Then go to your template and add this:
{% if first_login==True%}
# Put anything you want to be done
# In my case I wanted to open a new window by using script.
<script>
window.open("popUpWindow")
</script>
{%endif%}

DJango HttpResponseRedirect not passing "request" to function

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.

Best way to display invalid login details message--django forms

I want to display an error message to users along the lines of 'invalid username or password, please try again' for a login form in django if authentication fails, but im not sure what the best way to go about doing this is.
I've considered setting a context variable which will be passed into a template and then I could use CSS to present the message with the form. Something like below:
if user is not None:
if user.is_active:
# Redirect to a success page.
else:
# Return a 'disabled account' error message
else:
form = LoginForm()
incorrect_login = True
context = ('incorrect_login': incorrect_login, 'form':form)
return render(request, 'home/home.html', context)
# Return an 'invalid login' error message.
And the html:
<form action="." method="POST"> {%csrf_token%}
{%if incorrect_login%}
<table class='failed_login'>
{{form.as_table}}
</table>
{%else%}
<table class='successful_login'>
{{form.as_table}}
</table>
{%endif%}
<p><input type='submit' value='Submit'></p>
</form>
<!--Dont worry about the exact implementation of the html, its the basic idea im concerned with-->
However, I feel like this is a common problem and thus there is likely a better solution provided by django within the forms. I've looked into the docs on working with forms but im not sure how to approach, the main problem being that the errors stored in the form fields seem more about validating input type. Any help or a point in the right direction would be appreciated.
Django comes with built in authentication views, including one to log in. You should think about using the login view, or at least look at the code to see how it works.
One key thing is that a blank form is only created for GET requests. The problem in your view is that you always create a new form with form = LoginForm() when user is None. That means that the errors from the bound form (form = LoginForm(request.POST)) are not shown to the user.
Im going to share this approach with you, maybe it could help :
Views.py
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect
from django.views.generic import View
from django.core.urlresolvers import reverse
from django.contrib import messages
from django.contrib.auth import login, authenticate, logout
from ..form import UsersForm
class LoginView(View):
template_name = ['yourappname/login.html', 'yourappname/home.html']
def get(self, request, *args, **kwargs):
form = UsersForm()
if request.user.is_authenticated():
return render(request, self.template_name[1], t)
return render(request, self.template_name[0], t)
def post(self, request, *args, **kwargs):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username = username, password = password)
if user is not None:
login(request, user)
if user.is_active:
return render(request, self.template_name[ 1 ])
else:
messages.add_message(
request, messages.ERROR, "Incorrect user or password"
)
return HttpResponseRedirect(reverse( 'yourappname:login' ))
As i see you already know the template interaction, sending by post the user and password and using django messages.
If you wish to manage the errors from the form you can use the clean method :
https://docs.djangoproject.com/en/1.9/ref/forms/validation/

Beginner Django: Authenticating/logging in a User

Hello! I'm having trouble with the authentication system. I've followed the documentation pretty closely, but I just can't seem to get this to work. The problem seems to be that when I call the authenticate method with my cleaned form data, it's not returning anything. It's clearly doing this in the web page (it just returns the render request at the bottom every time I submit the form), and I tried authenticating in the same way via the shell and am also returning True for 'user is None'.
I'm wondering if perhaps the problem is that I haven't included the proper middleware? My MIDDLEWARE_CLASSES are as follows:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
It appears that I have everything necessary, but I'm just not sure.
In any case, here's the code for my view:
from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse
from django.contrib.auth.models import User
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import authenticate, login
def user_login(request):
if request.method == 'POST':
form = AuthenticationForm(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:
if user.is_active:
login(request, user)
return HttpResponse("Good Job")
else:
return HttpResponse("Inactive User")
else:
return HttpResponse("Bad Job")
else:
form = AuthenticationForm()
return render(request, 'myapp/login_form.html', {
'form': form,
})
And here is my very simple login_form.html template:
<h1>Login</h1>
<form action="/login/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
UPDATE: I have implemented the following solution:
changed the line
form = AuthenticationForm(request.POST)
to
form = AuthenticationForm(data = request.POST)
Now I am able to login via the superuser account, but username/password combinations for ordinary accounts are not recognized. If I submit the credentials for a regular user, the form is re-rendered plus the following message:
Please enter a correct username and password. Note that both fields may be case-sensitive.
Any ideas?
UPDATE 2
It turns out I had an error in my registration form such that it wasn't properly storing the password for new users registered via that form. I was doing password assignment in the constructor for a new User object, when instead you need to:
User.objects.create_user('username', 'email', 'password')
Rookie mistake! Thanks for the help.
Try form = AuthenticationForm(data = request.POST)
From the django git for AuthenticationForm:
def __init__(self, request=None, *args, **kwargs):
"""The 'request' parameter is set for custom auth use by subclasses.
The form data comes in via the standard 'data' kwarg.`
"""

How to allow users to change their own passwords in Django?

Can any one point me to code where users can change their own passwords in Django?
Django comes with a user
authentication system. It handles user
accounts, groups, permissions and
cookie-based user sessions. This
document explains how things work.
How to change Django passwords
See the Changing passwords section
Navigation to your project where manage.py file lies
$ python manage.py shell
type below scripts :
from django.contrib.auth.models import User
u = User.objects.get(username__exact='john')
u.set_password('new password')
u.save()
You can also use the simple manage.py command:
manage.py changepassword *username*
Just enter the new password twice.
from the Changing passwords section in the docs.
If you have the django.contrib.admin in your INSTALLED_APPS, you can visit: example.com/path-to-admin/password_change/ which will have a form to confirm your old password and enter the new password twice.
You can also just use the django.contrib.auth.views.password_change view in your URLconf. It uses a default form and template; supplying your own is optional.
This tutorial shows how to do it with function based views:
View file:
from django.contrib import messages
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.forms import PasswordChangeForm
from django.shortcuts import render, redirect
def change_password(request):
if request.method == 'POST':
form = PasswordChangeForm(request.user, request.POST)
if form.is_valid():
user = form.save()
update_session_auth_hash(request, user) # Important!
messages.success(request, 'Your password was successfully updated!')
return redirect('change_password')
else:
messages.error(request, 'Please correct the error below.')
else:
form = PasswordChangeForm(request.user)
return render(request, 'accounts/change_password.html', {
'form': form
})
Url file:
from django.conf.urls import url
from myproject.accounts import views
urlpatterns = [
url(r'^password/$', views.change_password, name='change_password'),
]
And finally, the template:
<form method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Save changes</button>
</form>
Its without need to go to shell enter passwd and reenter passwd
python manage.py changepassword <username>
or
/manage.py changepassword <username>
Using shell
python manage.py shell
from django.contrib.auth.models import User
users=User.objects.filter(email='<user_email>')
#you can user username or etc to get users query set
#you can also use get method to get users
user=users[0]
user.set_password('__enter passwd__')
user.save()
exit()
urls.py:
urlpatterns = [
url(r'^accounts/', include('django.contrib.auth.urls')),
Template:
{% trans "Change password" %}
Documented at: https://docs.djangoproject.com/en/1.9/topics/auth/default/#using-the-views
Per the documentation, use:
from django.contrib.auth.hashers import makepassword
The main reason to do this is that Django uses hashed passwords to store in the database.
password=make_password(password,hasher='default')
obj=User.objects.filter(empid=emp_id).update(username=username,password=password)
I used this technique for the custom user model which is derived from the AbstractUser model. I am sorry if I technically misspelled the class and subclass, but the technique worked well.
Authentication is the one way and after that reset the password
from django.contrib.auth import authenticate
user = authenticate(username='username',password='passwd')
try:
if user is not None:
user.set_password('new password')
else:
print('user is not exist')
except:
print("do something here")
Once the url pattern is added as shown in Ciro Santilli's answer, a quick way to allow users to change passwords is to give them "staff access" for the admin functions. If you don't add them to any groups or give them special permissions, they can still change their password by going to the example.com/admin page. The staff access lets them go to the page even if it is blank; in the upper right corner they can click "change password" and use the admin funtionality.
This is the command i used, just in case you are having problem in that throw AttributeError: Manager isn't available; 'auth.User' has been swapped for 'users.User'.
python manage.py shell -c "from django.contrib.auth import get_user_model;
User = get_user_model();
u = User.objects.get(username='admin');
u.set_password('password123');
u.save()"
Very similar to #Ciro's answer, but more specific to the original question (without adding all the authentication views):
just add to urlpatterns in urls.py:
url('^change-password/$', auth_views.password_change, {'post_change_redirect': 'next_page'}, name='password_change'),
Note that post_change_redirect specifies the url to redirect after the password is changed.
Then, just add to your template:
Change Password
view.py
views.py
def changepassword(request):
if request.method == "POST":
user_id = request.POST['user_id']
oldpassword = request.POST['oldpassword']
newpassword = request.POST['newpassword']
user = User.objects.get(id=user_id)
if **user.check_password**(oldpassword):
**user.set_password(newpassword)**
user.save()
return redirect("app:login-user")
else:
messages.success(request,"Pervious Password Not Match")
return redirect("app:changepassword")
else:
return render(request,'app/changepassword.html')
url.py
path('changepassword',views.changepassword,name='changepassword'),

Categories

Resources