want to improve my view - django

I've view like this. It worked. I'm new to django. Can you please help me to improve this code? thank you
def getAPI(request):
username = request.GET.get('username')
password = request.GET.get('password')
#TODO Match user and password
if username:
user = User.objects.get(username__exact=username)
is_exist = user.check_password(password)
if is_exist == True:
api_key = ApiKey.objects.get(id=user.id)
else:
error_message = 'username or password is invalid.'
return render_to_response('details.html',locals(),
context_instance=RequestContext(request)
)
if username and password does not exist Then I want to print error message. Otherwise I want to print ApiKey. thanks

Do you mean "print" (in which case just use python's print function) or do you want to return it in the response? If the latter, read up about django templates and passing variables to render_to_response.
Also, sticking a password as a GET variable is a bit of a bad idea, since it'll be visible on the URL:
http://example.com/whatever?username=me&password=s3cr3t
User/pass info should normally be sent via POST from a form. But maybe you're not that bothered about security.

Here's the basic template to authenticate a user:
from django.contrib.auth import authenticate
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:
# User is authenticated - return api key
else:
# Return a 'disabled account' error message
else:
# Return an 'invalid login' error message.

Related

How to update User password in django

I'm having trouble when i try to update user password in django.
def password(request):
if request.method=="POST":
password =request.user.password
username=request.user.username
c_password=request.POST["current_password"]
new_password=request.POST["new_password"]
r_new_password=request.POST["retype_new_password"]
if password==c_password:
if new_password==r_new_password:
user =User.objects.get(username=username)
user.set_password(new_password)
user.save()
messages.info(request,"Successfully saved")
else:
messages.info(request,"PASSWORD DOES NOT MATCH")
else:
messages.info(request,"PASSWORD INCORRECT")
return render(request,"security.html")
When i fill the current password, it is giving me error password incorrect. But, when i fill pbkdf2_sha256$320000$Cb4s4nwqKwirdgo50ZdjLH$aeuSP3X+dSZXsv0XJB0XxkpwfsmU+PedMX9Jl50Zark=
, my password becomes correct and user password is updateable. My problem is I would like to fill in current password field as normal current password without getting the error.
You use authenticate(…) [Django-doc] to validate the password: this will retrieve the hashing algorithm and the salt, and check if the hashes match, so you can work with:
def password(request):
if request.method == 'POST':
c_password = request.POST['current_password']
new_password = request.POST['new_password']
r_new_password = request.POST['retype_new_password']
user = authenticate(username=request.user.username, password=c_password)
if user is not None:
if new_password == r_new_password:
user.set_password(new_password)
user.save()
messages.info(request, 'Successfully saved')
else:
messages.info(request, 'PASSWORDS DOE NOT MATCH')
else:
messages.info(request, 'PASSWORD INCORRECT')
return render(request, 'security.html')
There is however a PasswordChangeView [Django-doc] to change the password: this already implements the logic and uses a form. You can inject a different template, for example with:
path(
'password/change/',
PasswordChangeView.as_view(template_name='security.html'),
name='password_change'
)
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
Note: It is better to use a Form [Django-doc]
than to perform manual validation and cleaning of the data. A Form will not
only simplify rendering a form in HTML, but it also makes it more convenient
to validate the input, and clean the data to a more convenient type.
Refer the Documentation Django does not store raw (plain text) passwords on the user model
use authenticate function instead of using if password==c_password:.
from django.contrib.auth import authenticate
def password(request):
if request.method=="POST":
password =request.user.password
username=request.user.username
c_password=request.POST["current_password"]
new_password=request.POST["new_password"]
r_new_password=request.POST["retype_new_password"]
user = authenticate(username=username, password=c_password)
if user is not None:
if new_password==r_new_password:
user =User.objects.get(username=username)
user.set_password(new_password)
user.save()
messages.info(request,"Successfully saved")
else:
messages.info(request,"PASSWORD DOES NOT MATCH")
else:
messages.info(request,"PASSWORD INCORRECT")
return render(request,"security.html")

Authenticating a User, without using Django rest framework?

Hey everyone I have a couple questions in regards to refactoring some old api endpoints as far as authentication goes. I have a view for example...
#csrf_exempt
# PARAMETERS: username, password
def submit_offer(request):
"""Submit an offer"""
username = request.GET.get("username")
password = request.GET.get("password")
# Authenticate user to set instance.user value into BuyerForm
user = authenticate(username=username, password=password)
if not user:
# Always want our potential Buyer to be logged in & authenticated
return JsonResponse({'message': 'Please login to continue.'})
if request.method == 'POST':
form = BuyerForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
# sets current user as Buyer.user
instance.user = user
instance.save()
return JsonResponse({'success': True}, status=200)
else:
data = form.errors.as_json()
return JsonResponse(data, status=400, safe=False)
else:
return JsonResponse(data={'status': 403})
Now every view that uses a form, and needs to grab the instance.user, has the same lines of code below...now I thought using request.user would do the job, but when testing that way I am getting back an AnonymousUser, which is kind of confusing me?
username = request.GET.get("username")
password = request.GET.get("password")
# Authenticate user to set instance.user value into BuyerForm
user = authenticate(username=username, password=password)
Now is there a better way to authenticate the user, like in a regular django view using request.user, rather than having to manually authenticate the user in each view? (edited)
password = request.GET.get("password").
This is very vulnerable way to design a django app.
Please see
Accessing Username and Password in django request header returns None
BTW, write a custom middle ware and put your code there.
username = get_username_from_header
password = get_password_from_header
# Authenticate user to set instance.user value into BuyerForm
user = authenticate(username=username, password=password)
# Attach user to request
request.user = user
As each request are being passed through the middle-ware, you can access the user from each view.

Django authenticate method returns None

I am trying to create a user login. I am registering the user through django's admin page. Username and passwords are entered correctly.
Also I have tried adding authentication backends to settings.py
I have tried multiple ways but couldn't get it to work.
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)
My code looks like below :
models.py :
class Account(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
views.py:
def login(request):
if request.method == 'POST':
username = request.POST.get('user')
password = request.POST.get('pass')
user = authenticate(username=username,
password=password) ----------> None
if user:
if user.is_active():
login(request, user)
return HttpResponseRedirect(reverse('index'))
else:
return HttpResponse('Account not active')
else:
print('Someone tried to login and failed ')
print('Username {} and passowrd {}'.format(username, password))
return HttpResponse('Invalid login details supplied!!')
else:
return render(request,'account/login.html', {})
The username and password from the below ones are coming as empty so it is giving none
username = request.POST.get('user')
password = request.POST.get('pass')
Try to inspect the element from HTML to find the name of the fields from which the data is coming from the template or print the values of username and password variables to cross verify.
use request.POST.get('username'), request.POST.get('password1') but as told it totally depends on the html template. It is safer to clean the data and then go for authentication.
Django has inbuilt Class Based Views for the same purpose. Give them a try

invoke function just after user login in django

I was looking for a way to invoke a function (do_something) just after user logged-in.
def do_something(request):
# do blah-blah
return data
One way of doing is that I can check the referrer page using META['HTTP_REFERER'] if it comes through 'login' page or not.
But it doesn't make strong criteria if the page comes from any where else.
Is there any post_login_signal which can help me out for this issue.
There is the user_logged_in signal.
Create your own log in function. Something like the Django documentation example:
def login_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)
# Do what you want to do here
else:
# Return a 'disabled account' error message
else:
# Return an 'invalid login' error message.

Show captcha in Django only when the user enters wrong password for 3 times?

I have a login view like this:
def login_backend(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
state = "Username or Password Incorrect!"
if user is not None:
login(request, user)
return HttpResponseRedirect('/overview/')
else:
captcha = CaptchaField()
return render_to_response('login_backend.html', {'state':state,
'captcha':captcha }, context_instance=RequestContext(request))
else:
return render_to_response('login_backend.html', context_instance=RequestContext(request))
Now, if the user is wrong for more than one time, captcha is shown. However, I want to show captcha only when the user enters wrong password for more than 3 times. I think I can keep the track of the user attempt and if attempt > 3, I can show the captcha but I don't know how to implement it. How can I do this?
You can set the attempt variable in session data this way:
request.session['attempt'] = 1
and use session as a regular dict, which means using tools such as
if 'attempt' in request.session: