Testing url redirection in Django - python

If I go to http://localhost:8000/login/, login form will be displayed and you have to input username and password. If the credentials are right then you will be redirected to http://localhost:8000/dashboard/. The problem I am facing while testing is even though my username and password are correct it is not redirected to http://localhost:8000/dashboard/ but rather it goes to http://testserver/admin/login/?next=/dashboard/. I am using the below code to rest redirection functionality in django:
class UrlTests(TestCase):
def test_client_cart(self):
response = self.client.get('/login/')
self.assertEqual(200, response.status_code)
def test_login_client(self):
User.objects.create_user('rakesh', 'rrs402#nyu.edu', 'ranjan')
self.client.get('/login/')
self.client.login(username='rakesh', password='ranjan')
print self.client.get('/dashboard/')
Could anyone tell me why i am redirected to http://testserver/admin/login/?next=/dashboard/ instead http://localhost:8000/dashboard/.
In my settings.py file:
LOGIN_URL = '/'
LOGOUT_URL = '/logout/'
LOGIN_REDIRECT_URL = '/dashboard/'
LOGOUT_REDIRECT_URL = '/'
My application is working fine but I am not able to test redirection thing. Could anyone give me some pointers where I am going wrong?
If I print out print self.client.login(username='rakesh', password='ranjan') it is coming out to be True which means I am able to login but why not redirection ?
Update : I also tried using selenium
def login_user(self):
# User opens his web browser, and goes to the website
self.browser.get(self.live_server_url + '/login/')
# User types in his username and passwords and hits return
username_field = self.browser.find_element_by_name('username')
username_field.send_keys('rakesh')
password_field = self.browser.find_element_by_name('password')
password_field.send_keys('ranjan')
#User submits the form
password_field.send_keys(Keys.RETURN)
body = self.browser.find_element_by_tag_name('body')
print body.text
Here also I am getting the body.text of admin page but not dashboard page.
Update :
Dashboard view :
class PortalDashboardView(RequireStaffMixinView, TemplateView):
template_name = "portal/dashboard.html"

Because you aren't getting logged in. The password you are sending to the login call is different to the one you use when creating the user within your test case, so the credentials are invalid.
Note you don't need to call client.get('/login/') there, anyway.

Related

Getting cookies from a form submit and using them with a webtest

So I'm trying to do some test cases with webtest library, the problem is that my site has access control which requires a user to login. It seems that the form post is successful, but the result do not have any cookies (that I could find at least), and the cookiejar is empty after the login.
Test setup:
class TestMyViewSuccessCondition(unittest.TestCase):
def setUp(self):
self.config = testing.setUp()
from myapp import main
settings = {'sqlalchemy.url': postgresqlURL}
app = main({}, **settings)
from webtest import TestApp
self.testapp = TestApp(app, cookiejar=CookieJar())
Test:
page = self.testapp.get('/login', status=200)
self.assertIn('Please login', page)
form = page.forms['loginForm']
form['username'] = 'user'
form['password'] = 'userpw'
result = form.submit(status=200)
# self.testapp.cookies is empty dictionary at this point
# it fails here, login page is shown again
page = self.testapp.get('/home', status=200)
result returns 200 OK, and the HTML content of the login page, after the form submit, but no redirect is happening, is that a problem? or is that working as intended? Before the any access control other form submits worked just fine. The cookies will change every time when the user clicks a link or reloads the page. I'm using session cookies. I tried to set a unsecure flag for cookies.
and the last return of the my login view:
if 'form.submitted' in request.POST:
# do stuff
return HTTPFound(location=request.route_url('home'))
I would be using the normal unittest but since unittest module looses its nuts when the view tries to do redirect, someone suggested webtest library.
Problem was that the form.submit() didn't actually mimic the basic use-case of mine, where the user clicks the submit button. In normal case the browser adds the username, password and the ('form.submitted', '') in side of the request.POST. But the form.submit() only adds the username and password, and only those that are defined in the form, so I couldn't define my own values to go with the request. (at least I didn't found out how)
Problem was solved inside of the login view. by changing the if 'form.submitted' in request.POST: -> if 'username' in request.POST and 'password' in request.POST:
Cookies are working just fine, as show above, login failed to support my test.

Name of the user not getting displayed in python code

I have made a signup page using python. Following is the link to the code :
Signup Page Code
As soon as a user signs up, he should be redirected to /welcome which says :
Welcome user
But I cannot display it by the above mentioned code.
Whereas when I write
self.redirect('/welcome?username = '+user)
I get redirected to a page which says
Welcome user
Why is it so?
When you write:
self.redirect('/welcome?username=' + user) #no whitespaces in the url
you are adding to the url a GET parameter(of the type name=value), in your case username=user.
So, when your welcomeHandler class handles the get request:
username=self.request.get('username')
it sets the username to the value of the GET parameter in the url with the name 'username' (username = user) and your welcome message is correctly displayed.
If you:
self.redirect('/welcome')
there are no GET parameters in the url and username is set to the default empty string and just Welcome is displayed.
Check here the Request documentation.

request.user.is_authenticated() in django views is always returning false

I am trying Google Oauth2 key,id using django-social-auth to setup a google+ login to my website. I included 2 function defs in views.py, one for index and other profile. So the login is attempted in index and if there is a pass it HttpResponseRedirects to profile page. I am stuck at this point where the login dialog for google+ pops up, i enter the user credentials and it is accepted. However, the index is not redirecting to profile page. In the code below if you see, the request.user.is_authenticated() is always returning false. On printing the request.user i always get AnonymousUser. Please let me know if i am doing anything wrong here or i need to add something to the code.
My views.py currently looks like this.
def index(request):
#print request.user
if request.user.is_authenticated():
print "user is authenticated"
return HttpResponseRedirect('/profile')
return render_to_response('index.html', {}, context_instance=RequestContext(request))
def profile(request):
return render_to_response('profile.html')
The settings file has the following parameters related :
GOOGLE_OAUTH2_CLIENT_ID = <client-id>
GOOGLE_OAUTH2_CLIENT_SECRET = <secret-key>
GOOGLE_OAUTH2_USE_UNIQUE_USER_ID = True
LOGIN_URL = '/'
LOGIN_REDIRECT_URL = '/profile/'
LOGIN_ERROR_URL = '/login-error/'
AUTHENTICATION_BACKENDS = (
'social_auth.backends.google.GoogleOAuthBackend',
'social_auth.backends.google.GoogleOAuth2Backend',
'social_auth.backends.google.GoogleBackend',
'social_auth.backends.OpenIDBackend',
'django.contrib.auth.backends.ModelBackend',
)
I followed this google developer's page in doing this task.
I tried the link w.r.t RequestContext solution and a solution mentioned in similar problem, but both weren't fruitful.

Redirect in flask does not actually redirect to the desired page.

class XX(MethodView):
def get(self):
....
def post(self):
error = None
user = request.form['username']
password = request.form['password']
print user,password
if user == 'xxx' and password == 'xx':
session['logged_in'] = True
session['session_user'] = 'xx'
return redirect("control")
else:
errors = []
errors.append("Login error")
return render_template("login.html" , errors=errors)
#adding rule for control Blueprint
control.add_url_rule("/control",view_func= ControlView.as_view('control'))
The code snippet checks for specific username,password and should redirect to a specific page.
When requested for the login page, a GET request is sent.The above snippet gets username and password and adds to session dictionary.The redirect method results in a POST request and response code is 302 FOUND followed by a GET request to desired page with 200 OK response code.
But the redirection does not happen, it remains on same login page.
what should redirect have as parameters?
redirect('control')
redirect(url_for('control'))
redirect(url_for('control.control'))
Why using render_template('XX.html') responds with 500 response code ??
Is this code inside of a blueprint named 'control'? I'm guessing yes, based on the code shown above.
When you're using blueprints, you cannot know the final URL (eg: /control) in advance, since the blueprint user can map the base URL anywhere they'd like.
The best way to redirect to your view, assuming this is a blueprint, is using the blueprint URL notation: redirect(url_for('control.control')).
If this is NOT going to be used in a blueprint, you should be able to do something like: redirect(url_for('control')) so long as that's your view name when added to the route.
Hope this was clear.
If you're still having errors when trying to two above examples, enable Flask debugging (app.config['DEBUG'] = True) and re-try. The traceback should explain what's happening in more depth.

css working on all but two pages

Specifically, pages using an optional regular expression. By optional, I mean PAGE_RE below.
I am creating a Wiki. If a user searches a term, and that term doesn't already exist, then the user is redirected to an edit page so they can create the new content. This only happens, however, if the user is logged in. To determine if the user is logged in, I check for a cookie. If the user isn't logged in(no cookie), then I redirect, not to the edit page, to create the new content, but to the login page, dealt with by the Login class below. The user logs in, a cookie is created, and then they are redirected to the edit page to create the content they originally searched for. In order to remember what their topic was, so I can redirect after the login, I send the topic(in the form '/topic') to the Login class, where it's received as a parameter by the get and post methods. If a user just comes to the site and logs in normally, they are redirected to the home page, but in this case, because the topic has been received by get and post and is not None, I use the line self.redirect('/edit/%s' % topic[1:]) below, to send them on to their original destination. The problem is, css isn't working for the two urls in below that use PAGE_RE. JsFiddler4 shows that there is a 404 involving /login/css/wiki.css. It suddenly clicked after some time that that url is not the url for the login page when it receives the extra 'topic' param. It is also the case with EditPage. How can I get css to work on these pages/urls when they are sometimes different? I didn't know what was going on for ages, then I downloaded and ran JsFiddler4 and figured it out. I am using Google App Engine, webapp2, jinja2. Any help much appreciated. Apart from those two pages, css works fine.
This code is out of order and incomplete, but I hope it's sufficient
PAGE_RE = r'(/?(?:[A-Za-z0-9_-]+/?)*)'
app = webapp2.WSGIApplication([
('/signup', Register),
('/logout', Logout),
('/login' + PAGE_RE, Login),
('/edit' + PAGE_RE, EditPage),
('/', Front),
(PAGE_RE, WikiPage),
], debug=True)
class Login(Main):
""" Validate form and validate users cookie """
def get(self, topic):
self.render('login.html', error={})
def post(self, topic):
username = self.request.get('username')
password = self.request.get('password')
if not username or not self.valid(user=username):
self.login_error(user=username)
elif not password or not self.valid(pw=password):
self.login_error(user=username)
elif not self.user_exists(username):
self.render('login.html', error={'no_user':'That user does not exist'})
else:
self.login(username, password, topic=topic)
def login(self, name, pw, topic):
user_hash = User.get_user_hash(name)
if self.valid_pw(name, pw, user_hash):
self.create_secure_cookie('user_id', name)
if topic:
self.redirect('/edit/%s' % topic[1:])
else:
self.redirect('/')
else:
self.login_error(user=name)
def login_error(self, user):
self.render('login.html', username=user, error={'login': errors['login']})
def valid_pw(self, name, pw, user_hash):
salt = user_hash.split('|')[0]
return user_hash == self.create_user_hash(name, pw, salt)
Ok, I solved this. Here's what appeared to be happening.
This redirect was sending a parameter to the Login class above:
self.redirect('login/%s' % wiki_topic) #wiki_topic = something like 'topic'
when looking for the css for a page, what seems to happen is that the last part of the path up to the '/' is taken off, and replaced by the path to the css, '/css/wiki.css' in my case.
So I was passing 'login/topic' and just 'topic' was being replaced by the css path to give:
'login/css/wiki.css' instead of the correct just 'css/wiki/css'.
To stop this from happening, I changed the line redirecting to the Login class from:
self.redirect('login/%s' % wiki_topic) to >> self.redirect('login%s' % wiki_topic)
the second version has no slash before the %s.

Categories