Diafotismos
Diafotismos

Reputation: 109

How can one obtain the name of the currently logged-in user with this Python code?

Of course, I hate resorting to using the time of busy StackExchange members to solve my issues, but I have asked in the forums from which I retrieved this code to explain how the mechanism works, but there has been absolutely no response.

My question should probably be quite simple (not for myself, as I am what you would call a web development amateur). I have this code (not my own) for the backend a basic blog. But there is one thing that I am not quite understanding. In one of the HTML files, there is a line that has {{user.name}}, which gets the username of the person currently logged in and posts it in the corner of the page. The {{}} is just Jinja2 syntax that prints a python expression to the template (or so I'm told).

How can I get the username of the user logged in within the Python file? What I am currently trying to do in my own web application, is obtain the username of the user logged in and Query the Google Datastore for the information regarding the user and put in on a profile page, like so:

class Profile(BlogHandler):
    def render_profile(self):
        signatory = user.name
        signedevents = db.GqlQuery("SELECT event FROM Signatories WHERE username IN (signatory)")
        self.render("profile.html", signedevents=signedevents)
    def get(self):
        if self.user:
            self.render_profile()
        else:
            self.redirect('/')

But whenever I try this, I always get an error. Is there something else that should go in place of user.name?

Blog code (I am sure the answer is somewhere in the Handler class but I simply cannot figure out what the issue is):

import os
import re
import random
import hashlib
import hmac
from string import letters

import webapp2
import jinja2

from google.appengine.ext import db

template_dir = os.path.join(os.path.dirname(__file__), 'templates')
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(template_dir),
                               autoescape = True)

secret = 'fart'

def render_str(template, **params):
    t = jinja_env.get_template(template)
    return t.render(params)

def make_secure_val(val):
    return '%s|%s' % (val, hmac.new(secret, val).hexdigest())

def check_secure_val(secure_val):
    val = secure_val.split('|')[0]
    if secure_val == make_secure_val(val):
        return val

class BlogHandler(webapp2.RequestHandler):
    def write(self, *a, **kw):
        self.response.out.write(*a, **kw)

    def render_str(self, template, **params):
        params['user'] = self.user
        return render_str(template, **params)

    def render(self, template, **kw):
        self.write(self.render_str(template, **kw))

    def set_secure_cookie(self, name, val):
        cookie_val = make_secure_val(val)
        self.response.headers.add_header(
            'Set-Cookie',
            '%s=%s; Path=/' % (name, cookie_val))

    def read_secure_cookie(self, name):
        cookie_val = self.request.cookies.get(name)
        return cookie_val and check_secure_val(cookie_val)

    def login(self, user):
        self.set_secure_cookie('user_id', str(user.key().id()))

    def logout(self):
        self.response.headers.add_header('Set-Cookie', 'user_id=; Path=/')

    def initialize(self, *a, **kw):
        webapp2.RequestHandler.initialize(self, *a, **kw)
        uid = self.read_secure_cookie('user_id')
        self.user = uid and User.by_id(int(uid))

def render_post(response, post):
    response.out.write('<b>' + post.subject + '</b><br>')
    response.out.write(post.content)

class MainPage(BlogHandler):
  def get(self):
      self.write('Hello, Udacity!')


##### user stuff
def make_salt(length = 5):
    return ''.join(random.choice(letters) for x in xrange(length))

def make_pw_hash(name, pw, salt = None):
    if not salt:
        salt = make_salt()
    h = hashlib.sha256(name + pw + salt).hexdigest()
    return '%s,%s' % (salt, h)

def valid_pw(name, password, h):
    salt = h.split(',')[0]
    return h == make_pw_hash(name, password, salt)

def users_key(group = 'default'):
    return db.Key.from_path('users', group)

class User(db.Model):
    name = db.StringProperty(required = True)
    pw_hash = db.StringProperty(required = True)
    email = db.StringProperty()

    @classmethod
    def by_id(cls, uid):
        return User.get_by_id(uid, parent = users_key())

    @classmethod
    def by_name(cls, name):
        u = User.all().filter('name =', name).get()
        return u

    @classmethod
    def register(cls, name, pw, email = None):
        pw_hash = make_pw_hash(name, pw)
        return User(parent = users_key(),
                    name = name,
                    pw_hash = pw_hash,
                    email = email)

    @classmethod
    def login(cls, name, pw):
        u = cls.by_name(name)
        if u and valid_pw(name, pw, u.pw_hash):
            return u

Everything past here is probably not important, but if the answer cannot be found by only using the code above, please continue.

##### blog stuff

def blog_key(name = 'default'):
    return db.Key.from_path('blogs', name)

class Post(db.Model):
    subject = db.StringProperty(required = True)
    content = db.TextProperty(required = True)
    created = db.DateTimeProperty(auto_now_add = True)
    last_modified = db.DateTimeProperty(auto_now = True)

    def render(self):
        self._render_text = self.content.replace('\n', '<br>')
        return render_str("post.html", p = self)

class BlogFront(BlogHandler):
    def get(self):
        posts = greetings = Post.all().order('-created')
        self.render('front.html', posts = posts)

class PostPage(BlogHandler):
    def get(self, post_id):
        key = db.Key.from_path('Post', int(post_id), parent=blog_key())
        post = db.get(key)

        if not post:
            self.error(404)
            return

        self.render("permalink.html", post = post)

class NewPost(BlogHandler):
    def get(self):
        if self.user:
            self.render("newpost.html")
        else:
            self.redirect("/login")

    def post(self):
        if not self.user:
            self.redirect('/blog')

        subject = self.request.get('subject')
        content = self.request.get('content')

        if subject and content:
            p = Post(parent = blog_key(), subject = subject, content = content)
            p.put()
            self.redirect('/blog/%s' % str(p.key().id()))
        else:
            error = "subject and content, please!"
            self.render("newpost.html", subject=subject, content=content, error=error)


###### Unit 2 HW's
class Rot13(BlogHandler):
    def get(self):
        self.render('rot13-form.html')

    def post(self):
        rot13 = ''
        text = self.request.get('text')
        if text:
            rot13 = text.encode('rot13')

        self.render('rot13-form.html', text = rot13)


USER_RE = re.compile(r"^[a-zA-Z0-9_-]{3,20}$")
def valid_username(username):
    return username and USER_RE.match(username)

PASS_RE = re.compile(r"^.{3,20}$")
def valid_password(password):
    return password and PASS_RE.match(password)

EMAIL_RE  = re.compile(r'^[\S]+@[\S]+\.[\S]+$')
def valid_email(email):
    return not email or EMAIL_RE.match(email)

class Signup(BlogHandler):
    def get(self):
        self.render("signup-form.html")

    def post(self):
        have_error = False
        self.username = self.request.get('username')
        self.password = self.request.get('password')
        self.verify = self.request.get('verify')
        self.email = self.request.get('email')

        params = dict(username = self.username,
                      email = self.email)

        if not valid_username(self.username):
            params['error_username'] = "That's not a valid username."
            have_error = True

        if not valid_password(self.password):
            params['error_password'] = "That wasn't a valid password."
            have_error = True
        elif self.password != self.verify:
            params['error_verify'] = "Your passwords didn't match."
            have_error = True

        if not valid_email(self.email):
            params['error_email'] = "That's not a valid email."
            have_error = True

        if have_error:
            self.render('signup-form.html', **params)
        else:
            self.done()

    def done(self, *a, **kw):
        raise NotImplementedError

class Unit2Signup(Signup):
    def done(self):
        self.redirect('/unit2/welcome?username=' + self.username)

class Register(Signup):
    def done(self):
        #make sure the user doesn't already exist
        u = User.by_name(self.username)
        if u:
            msg = 'That user already exists.'
            self.render('signup-form.html', error_username = msg)
        else:
            u = User.register(self.username, self.password, self.email)
            u.put()

            self.login(u)
            self.redirect('/blog')

class Login(BlogHandler):
    def get(self):
        self.render('login-form.html')

    def post(self):
        username = self.request.get('username')
        password = self.request.get('password')

        u = User.login(username, password)
        if u:
            self.login(u)
            self.redirect('/blog')
        else:
            msg = 'Invalid login'
            self.render('login-form.html', error = msg)

class Logout(BlogHandler):
    def get(self):
        self.logout()
        self.redirect('/blog')

class Unit3Welcome(BlogHandler):
    def get(self):
        if self.user:
            self.render('welcome.html', username = self.user.name)
        else:
            self.redirect('/signup')

class Welcome(BlogHandler):
    def get(self):
        username = self.request.get('username')
        if valid_username(username):
            self.render('welcome.html', username = username)
        else:
            self.redirect('/unit2/signup')

app = webapp2.WSGIApplication([('/', MainPage),
                               ('/unit2/rot13', Rot13),
                               ('/unit2/signup', Unit2Signup),
                               ('/unit2/welcome', Welcome),
                               ('/blog/?', BlogFront),
                               ('/blog/([0-9]+)', PostPage),
                               ('/blog/newpost', NewPost),
                               ('/signup', Register),
                               ('/login', Login),
                               ('/logout', Logout),
                               ('/unit3/welcome', Unit3Welcome),
                               ],
                              debug=True)

If there is something you need me to clarify, please let me know. Thank you in advance for your help.

Upvotes: 0

Views: 728

Answers (2)

inSynergy
inSynergy

Reputation: 77

Hi I remember this thing with App Engine, maybe it has to do something with the old 'db' datastore. Google now recommends to use 'ndb'. Since you are also setting cookie you can actually use it to render your user's name in the Welcome page.

This is how I got around it, hope this helps.

class Register(SignUp):
    def done(self):
        #make sure the user doesn't already exist
        u = User.by_name(self.request.get("username"))
        if u:
            msg = 'That user already exists.'
            self.render('signup-form.html', username_exists = msg)
        else:
            username = self.request.get("username")
            password = self.request.get("password")
            email = self.request.get("email")

            u = User.register(username, password , email)
            u.put()
            self.login(u)
            self.redirect('/blog/welcome')


class Welcome(BlogHandler):
    def get(self):        
        cookie = self.request.cookies.get("user_id")
        val = check_secure_val(cookie)
        u = User.by_id(int(val))

        if u:
            print u
            self.render('welcome.html', username = u.name)
        else:
            self.redirect('/blog/signup')

Upvotes: 0

Dan Cornilescu
Dan Cornilescu

Reputation: 39814

OK, you're inheriting BlogHandler.

To get the username info, by following the Unit3Welcome() example, I think you need to change signatory = user.name to signatory = self.user.name

To fill the {{user.name}} field in a jinja2 template it needs to get in the template values dict it receives a user variable (also of dict type) containing a name key (presumably with the respective username). For example: {'user': {'name': 'johndoe'}}.

I'm not familiar neither with how the renderer you use works nor with SQL and how signedevents is filled, so you may need to adapt.

To easily inspect (in debug print style) what actually makes it to the template you can temporarily insert a paragraph like this somewhere in your html: <p>user: ({{ user }})</p> and you should get the dump of the user variable right in your browser :)

Upvotes: 1

Related Questions