Hi I added reCAPTCHA to a page so far that it can verify a client. Now I want a more graceful failure when isHuman = Falsewith a redirect to the form page in such case with a message on the form page that reCAPTCHA failed. Can you inform what to do rather than just outputting "captcha failed?" so that it can redirect to the form page with Google App Engine's request handler? Here's my code:
def post(self, view): #edit
challenge = self.request.get('recaptcha_challenge_field')
response = self.request.get('recaptcha_response_field')
remoteip = os.environ['REMOTE_ADDR']
cResponse = captcha.submit(
challenge,
response,
CAPTCHA_PRV_KEY,
remoteip)
if cResponse.is_valid==True:
isHuman=True
else:
isHuman=False
self.response.out.write('captcha failed')
return
If you are just looking for a way to redirect back to your original posting page you can use:
self.redirect('your_url')
You could also include a GET variable in the url so that the page is aware that the CAPTCHA failed.
Related
So I hit a login route(python) from my frontend(react) that returns a auth_url to login using oauth. Then it needs to wait for the user to sign on and redirect back to frontend. Atm I can't figure out how to do both.
Either my frontend fetches the url, then window.location.replace(url), you sign on, then since the login route is only sending the url, there is no redirect back to frontend. Once logged on it just shows backend with a page showing auth_url
Or my frontend just makes the call to log on, and the backend redirects to auth_url without a way to redirect after completion to the frontend.
I can’t find any examples online of redirecting twice so it seems my logic is wrong. Is putting the url in a header the thing people do here?
My attempt:
async def test(url):
#redirect to oauth to sign in
await url
return redirect(url)
async def test2(testfinish):
# after oauth is complete, redirect to my frontend
await testfinish
return redirect('http://localhost:3000/')
#app.route("/login")
def login():
session["flow"] = _build_auth_code_flow(scopes=SCOPE)
auth_url=session["flow"]["auth_uri"]
return test2(test(auth_url))
My form resubmits every time I refresh the page. I want to send context with my render
if request.method == 'POST' and 'search_form' in request.POST:
rol = request.POST['rol']
group = request.POST['group']
national_number = request.POST['national_number']
phone_number = request.POST['phone_number']
users = MyUser.objects.filter(Q(group__name=group)|Q(role__name=rol)|Q(national_number=national_number)|Q(phone_number=phone_number))
return render(request,'deletuser.html',locals())
If you directly render a page as the result of a POST, then refreshing that page will resubmit the form, because that's how you got there.
The usual way to avoid this is to issue an HTTP redirect after a POST, instead of rendering content directly. Then the user ends up on a page via GET, which can be refreshed without problems.
You can google search for "redirect after post" to get more details.
I have a Django app that uses the builtin login system.
I'm trying to write a unit test that verifies that the login url redirects to home if the user is already authenticated. Meaning, if an already authenticated user tries to visit the login url, they get redirected to home.
This is a built-in feature of Django's LoginView, and I have verified that it is indeed working. However, I'm not sure how to write a unit test for this.
Question: How do I verify that this redirect occurs via unit tests? LoginView returns a TemplateResponse, which doesn't have a url parameter.
What I have so far is this:
from django.test import TestCase
from django.urls import reverse
home = reverse('home')
login = reverse('login')
logout = reverse('logout')
signup = reverse('signup')
USER_CREDS = { some users credentials }
class TestLoginView(TestCase):
def test_login_redirect(self):
self.client.post(signup, USER_CREDS)
self.client.get(logout)
self.client.post(login, USER_CREDS)
response = self.client.get(login)
self.assertRedirects(response, home)
EDIT:
SimpleTestCase.assertRedirects does not work for TemplateResponse objects.
TemplateResponse objects do not contain a url parameter, which is required for SimpleTestCase.assertRedirect.
The method raises the following error: AttributeError: 'TemplateResponse' object has no attribute 'url'
This is not the same as the linked question, because the response object from a LoginView is a TemplateResponse, not an HttpResponse.
You can check that the login process redirects to the desired named URL with assertRedirects:
SimpleTestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='', fetch_redirect_response=True)
Asserts that the response returned a status_code redirect status,
redirected to expected_url (including any GET data), and that the
final page was received with target_status_code.
Then in your test:
self.assertRedirects(response, home)
Edit
I've just had a similar problem, few notes:
Instead of performing the login process, you can use TestCase.force_login that skips the authentication and verification steps.
class TestLoginView(TestCase):
def test_login_redirect(self):
self.client.force_login(user)
# logged user retrieves the login page
response = self.client.get(login)
self.assertRedirects(response, home)
Response should be a 302 redirect to home: <HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="/">
If you are not getting a redirect when doing response = self.client.get(login) that means that it is loading the login page, which is what you don't want, so you have to fix that error.
So the problem is not that TemplateResponse objects do not contain a url parameter, it is that your login page isn't redirecting a logged in user to the home page.
Maybe a stupid question here:
Is Requests(A python HTTP lib) support Django 1.4 ?
I use Requests follow the Official Quick Start like below:
requests.get('http://127.0.0.1:8000/getAllTracks', auth=('myUser', 'myPass'))
but i never get authentication right.(Of course i've checked the url, username, password again and again.)
The above url 'http://127.0.0.1:8000/getAllTracks' matches an url pattern of the url.py of a Django project, and that url pattern's callback is the 'getAllTracks' view of a Django app.
If i comment out the authentication code of the 'getAllTracks' view, then the above code works OK, but if i add those authentication code back for the view, then the above code never get authenticated right.
The authentication code of the view is actually very simple, exactly like below (The second line):
def getAllTracks(request):
if request.user.is_authenticated():
tracks = Tracks.objects.all()
if tracks:
# Do sth. here
Which means if i delete the above second line(with some indents adjustments of course), then the requests.get() operation do the right thing for me, but if not(keep the second line), then it never get it right.
Any help would be appreciated.
In Django authentication works in following way:
There is a SessionMiddleware and AuthenticationMiddleware. The process_request() of both these classes is called before any view is called.
SessionMiddleware uses cookies at a lower level. It checks for a cookie named sessionid and try to associate this cookie with a user.
AuthenticationMiddleware checks if this cookie is associated with an user then sets request.user as that corresponding user. If the cookie sessionid is not found or can't be associated with any user, then request.user is set to an instance of AnonymousUser().
Since Http is a stateless protocol, django maintains session for a particular user using these two middlewares and using cookies at a lower level.
Coming to the code, so that requests can work with django.
You must first call the view where you authenticate and login the user. The response from this view will contain sessionid in cookies.
You should use this cookie and send it in the next request so that django can authenticate this particular user and so that your request.user.is_authenticated() passes.
from django.contrib.auth import authenticate, login
def login_user(request):
user = authenticate(username=request.POST.get('username'), password=request.POST.get('password'))
if user:
login(request, user)
return HttpResponse("Logged In")
return HttpResponse("Not Logged In")
def getAllTracks(request):
if request.user.is_authenticated():
return HttpResponse("Authenticated user")
return HttpResponse("Non Authenticated user")
Making the requests:
import requests
resp = requests.post('http://127.0.0.1:8000/login/', {'username': 'akshar', 'password': 'abc'})
print resp.status_code
200 #output
print resp.content
'Logged In' #output
cookies = dict(sessionid=resp.cookies.get('sessionid'))
print cookies
{'sessionid': '1fe38ea7b22b4d4f8d1b391e1ea816c0'} #output
response_two = requests.get('http://127.0.0.1:8000/getAllTracks/', cookies=cookies)
Notice that we pass cookies using cookies keyword argument
print response_two.status_code
200 #output
print response_two.content
'Authenticated user' #output
So, our request.user.is_authenticated() worked properly.
response_three = requests.get('http://127.0.0.1:8000/hogwarts/getAllTracks/')
Notice we do not pass the cookies here.
print response_three.content
'Non Authenticated user' #output
I guess, auth keyword for Requests enables HTTP Basic authentication which is not what is used in Django. You should make a POST request to login url of your project with username and password provided in POST data, after that your Requests instance will receive a session cookie with saved authentication data and will be able to do successful requests to auth-protected views.
Might be easier for you to just set a cookie on initial authentication, pass that back to the client, and then for future requests expect the client to send back that token in the headers, like so:
r = requests.post('http://127.0.0.1:8000', auth=(UN, PW))
self.token = r.cookies['token']
self.headers = {'token': token}
and then in further calls you could, assuming you're in the same class, just do:
r = requests.post('http://127.0.0.1:8000/getAllTracks', headers=self.headers)
from bottle import route, run, debug, error, request, template
#route('/home')
#route('/home/')
def login():
return template('templates/login')
#route('/home', method='POST')
#route('/home/', method='POST')
def welocme():
data = request.POST
if data:
password = data.get('password')
check_pass = 'password'
if password == check_pass:
return template('templates/welcome')
else:
return template('templates/login')
else:
return template('templates/login')
My requirement is:
I will get a login and welcome page on same url. Login page has only one password field.
My problem:
If I get login and go to welcome page again on refreshing, it send me to login page. But ideally it should be on the welcome page only.
#error(404)
def error404(error):
return 'http://google.com'
My second problem: I want to redirect on a particular url on 404.
If the user goes to the "/home" page, don't you want to check to see if they're logged in before showing them the login screen? It appears like you assume they're not already logged in if the HTTP method is not POST.
I don't know much about your framework, but I assume if the login is successful you should set a cookie, and then you should check the cookie for HTTP GETs to see if the user is authenticated.
Your second question is answered here.
You might also want to take a look at Beaker's cookie sessions and use that to keep your application's state between requests.
If I understand the question correctly, the only way to get to render the welcome template is via POST.
You could change this so that GET requests check whether someone is logged in. If that fails, then redirect them to the login page.