Im checking the examples google gives on how to start using python; especifically the code posted here; http://code.google.com/appengine/docs/python/gettingstarted/usingdatastore.html
The thing that i want to lean is that, here:
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting.put()
self.redirect('/')
They are saving a comment, IF the user is logged in, we save the user; if not its empty and when we get it out of the db we actually check for that here:
if greeting.author:
self.response.out.write('<b>%s</b> wrote:' % greeting.author.nickname())
else:
self.response.out.write('An anonymous person wrote:')
So what i would like is to use the User object to get the information, like this:
class Guestbook(webapp.RequestHandler):
def post(self):
user = users.get_current_user()
if user:
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting.put()
self.redirect('/')
else:
self.redirect(users.create_login_url(self.request.uri))
So, what i would like to do with that code is to send the user to the login url(if he is not logged in); and then to come back with whatever he had in post and actually post it. But what happens is that it doesnt even get to that action coz is nothing in the post.
I know i could put something in the session and check for it in the get action of the guestbook, but i wanted to check if someone could come up with a better solution!
Thanks
The problem is, self.redirect cannot "carry along" the payload of a POST HTTP request, so (from a post method) the redirection to the login-url &c is going to misbehave (in fact I believe the login URL will use get to continue when it's done, and that there's no way to ask it to do a post instead).
If you don't want to stash that POST payload around somewhere (session or otherwise), you can make your code work by changing the def post in your snippet above to def get, and of course the action="post" in the HTML written in other parts of the example that you haven't snipped to action="get". There are other minor workarounds (you could accept post for "normal" messages from logged-in users and redirect them to the get that perhaps does something simpler if they weren't logged in yet), but I think this info is sufficient to help you continue from here, right?
Related
I'm trying to get the details of the user who makes a get request in django. I'm using postman to perform the get request but when I try to print request.user and type(request.user):
#In the view
class SomeView(APIView):
....
....
def get(self, request, pk, format=None):
print(f'request: {request.user}, {type(request.user)')
I get None and None for the user and the type.
I've looked though many stackoverflow posts but I'm struggling finding out the reason.
From:
Django username is empty in a GET request
https://www.django-rest-framework.org/api-guide/authentication/
I thought perhaps I'm not performing the get request with a user, but if that is the case, I should be getting an Anonymous object as the type for user right? But instead it's telling me it's None
I should mention from postman I'm under the Authorization tab, I've tried using a Bearer Token which I know I had the correct token as well as (separately) using basic auth by having the username and the password. Either method results in request.user being None.
If I just print out request I get:
<rest_framework.request.Request: GET '/test/number/33574677/'>,
I'm not sure what the issue here is, does it have something to do with the way I'm using postman to send the request? Or perhaps I'm missing something very trivial? Thank you.
I'm trying to create user sessions as explained here http://www.essentialtech.co.nz/content/using_session_google_app_engine_and_python_27 . Below is the Login page handler class. Everything is fine, but I'm not able to understand what the 'self.session.get('referrer')' would do. I googled for it and found that 'HTTP_REFERER' refers to the site url where you are coming from. But why do we need it in the Login handler here? I feel glad if some one can explain it to me.
class LogIn(BaseHandler):
def get(self):
if self.session.get('user'):
del self.session['user']
if not self.session.get('referrer'):
self.session['referrer'] = \
self.request.environ['HTTP_REFERER'] \
if 'HTTP_REFERER' in self.request.environ \
else '/'
template_values = {
}
template = jinja_environment.get_template('login.html')
self.response.out.write(template.render(template_values))
def post(self):
user = self.request.get('user')
self.session['user'] = user
logging.info("%s just logged in" % user)
self.redirect('/')
I presume it's used to know where to redirect the user after login. But the POST redirects to '/' so doesn't look like it's plugged in, at least not in this snippet. This doesn't make sense though, if you come in from a totally different website. So maybe it's just used for logging / tracking purposes. Again, not detailed in this snippet.
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.
After being forced to leave PHP behind and work a bit with Python and Django I have hit a little problem.
What I'm trying to do is to use the built-in user-authentication that comes with Django. Problem is that when I'm trying to use the "login()" function it doesn't save the user in the session, or wherever it should be saved.
My code looks like this:
#csrf_exempt
def dologin(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.
return render_to_response('bsys/profile.html', {'message': 'Success!', 'user': request.user.get_full_name()})
else:
# Return a 'disabled account' error message
return render_to_response('bsys/login.html', {'message': 'Disabled!'})
else:
# Return an 'invalid login' error message.
return render_to_response('bsys/login.html', {'message': 'Sumthin Wong!'})
So problem is when I run:
request.user.get_full_name()
It says:
Exception Type: AttributeError
Exception Value: 'AnonymousUser' object has no attribute 'get_full_name'
So apparently it doesn't log in the user.
When I do the same, but using:
user.get_full_name()
It works, then the authenticate-function apparently works well too. So there is something about login(), I guess.
What I also tried was to login via the admin-login as an admin, then using the same request.user.get_full_name() from another view and it works fine.
Any ideas to solve this? Maybe I just missed some essential part of the framework.
I think the way you check that the user is logged in is causing this.
instead of:
if user is not None:
try with:
if user.is_authenticated:
This was it will get round the AnonymousUser case.
(it may be, don't remember from the top of my head)
if user.is_authenticated():
Why are you rendering a template on successful login? Like with all POSTed HTTP requests, it's a good idea to redirect on success to reduce the chance of the user resubmitting the request.
More relevantly, I believe this will fix your problem because the templates, when they get their context populated with the auth context processor, will have their {{ user }} variable set to the value of request.user, which is an anonymous user at the beginning of the request. If you redirect, the new request will have a non-anonymous request.user, so the template's value should be populated properly.
here's my code
def subscribe_current_user(self):
user1 = SocialNodeSubscription(parent=self.key)
user1.subscribed = True
current_user = users.get_current_user()
logging.error(current_user)
if current_user:
user1.user=current_user
else:
raise users.UserNotFoundError
user1.put()
The problem is that get_current_user returns None even if i'm logged in. It stores a None in the field user1.user and it prints a None in the log console.
How can i solve that?
Do you have login: required defined in app.yaml for your handler or have you provided a login url using users.create_login_url() so that the user can explicitly login.
Even if you are logged into google somewhere, users.get_current_user() won't
return a user object.
I have seen a lot of similar questions.
It helps to think of this line differently...
user = users.get_current_user()
This line doesn't search high and low in your browser and cache and retrieve whatever info and put it into a nice user object; it simply checks if an user is logged in to the app using the users class. Which means if you did not have the user logged with the users class, chances are this line of code won't do what you want it to do.
The important codes that should usually follow a get_current_user() method:
if user:
greeting = ('Welcome, %s! (sign out)' %
(user.nickname(), users.create_logout_url('/')))
else:
greeting = ('Sign in or register.' %
users.create_login_url('/'))
self.response.out.write('<html><body>%s</body></html>' % greeting)
I believed, you surely importing this,
from google.appengine.api import users
And also, Are you really authenticating django's 'User' model at the time of login?