【问题标题】:User Accounts with (Python 2.7 + Webapp2 + Google App Engine + Jinja + NDB + WTForms)用户帐户(Python 2.7 + Webapp2 + Google App Engine + Jinja + NDB + WTForms)
【发布时间】:2023-03-13 11:10:01
【问题描述】:

几周以来,我一直在绞尽脑汁,试图让这个身份验证模块在使用 Jinja、NDB 和 WTForms 的 webapp2 框架下工作。我在网上到处都看过,已经到了我的崩溃点,需要向某人寻求帮助。我一直在关注本教程(它非常详尽,但我认为遗漏了一些重要的细节,尤其是对于像我这样的新手):

User Accounts with Webapp2 + Google App Engine

据我所知,我已正确设置所有内容,但我不断收到 404 - 找不到资源。我可能做错了什么?这是我的代码...

handlers.py:

import webapp2

import sys
from google.appengine.ext import ndb
 sys.modules['ndb'] = ndb

import webapp2_extras.appengine.auth.models as auth_models

from google.appengine.api import users
from webapp2_extras import sessions, auth # we'll use auth later on
from webapp2_extras.auth import InvalidAuthIdError
from webapp2_extras.auth import InvalidPasswordError
from wtforms import Form, TextField, PasswordField, validators
from webapp2_extras.appengine.users import login_required


def jinja2_factory(app):
    j = jinja2.Jinja2(app)
    j.environment.filters.update({
    # Set filters. (http://tinyurl.com/jinja2-factory)
    # ...
})
    j.environment.globals.update({
        # Set global variables.
        'uri_for': webapp2.uri_for,
        # ...
    })
    return j


def login_required(handler):

    def check_login(self, *args, **kwargs):     
        if not self.user:
            return self.redirect_to('login')
        else:
            return handler(self, *args, **kwargs)
    return check_login    


class UserAwareHandler(webapp2.RequestHandler):

    def dispatch(self):        
        try:
            super(UserAwareHandler, self).dispatch()
        finally:
            # Save the session after each request        
            self.session_store.save_sessions(self.response)  

    @webapp2.cached_property
    def session_store(self):
        return sessions.get_store(request=self.request)

    @webapp2.cached_property
    def session(self):
        return self.session_store.get_session(backend="datastore")

    @webapp2.cached_property
    def auth(self):
        return auth.get_auth(request=self.request)

    @webapp2.cached_property
    def user(self):
        user = self.auth.get_user_by_session()
        return user

    @webapp2.cached_property
    def user_model(self):
        user_model, timestamp = self.auth.store.user_model.get_by_auth_token(
                self.user['user_id'], 
                self.user['token']) if self.user else (None, None)
        return user_model

    @webapp2.cached_property
    def jinja2(self):
        return jinja2.get_jinja2(factory=jinja2_factory, app=self.app)

    def render_response(self, _template, **context):
        ctx = {'user': self.user_model}
        ctx.update(context)
        rv = self.jinja2.render_template(_template, **ctx)
        self.response.write(rv)


class SignupForm(Form):
    email = TextField('Email', 
                [validators.Required(), 
                 validators.Email()])
    password = PasswordField('Password', 
                [validators.Required(), 
                 validators.EqualTo('confirm_password', 
                                message="Passwords must match.")])
    password_confirm = PasswordField('Confirm Password', 
                    [validators.Required()])


class SignupHandler(UserAwareHandler):
    #Serves up a signup form, creates new users
    def get(self):
        self.render_response("templates/signup.html", form=SignupForm())

    def post(self):
        form = SignupForm(self.request.POST)
        error = None
    if form.validate():
        success, info = self.auth.store.user_model.create_user(
            "auth:" + form.email.data,
            unique_properties=['email'],
            email= form.password.data,
            password_raw= form.password.data)

        if success:
            self.auth.get_user_by_password("auth:"+form.email.data, 
                                            form.password.data)
            return self.redirect_to("index")
        else:
            error = "That email is already in use." if 'email'\
                    in user else "Something has gone horrible wrong."

    self.render_response("templates/signup.html", form=form, error=error)


class LoginForm(Form):
    email = TextField('Email', 
                [validators.Required(), validators.Email()])
    password = PasswordField('Password', 
                [validators.Required()])


class LoginHandler(UserAwareHandler):
    def get(self):
        self.render_response("templates/index.html", form=LoginForm())

    def post(self):
        form = LoginForm(self.request.POST)
        error = None
        if form.validate():
            try:
                self.auth.get_user_by_password(
                        "auth:"+form.email.data, 
                        form.password.data)
                return self.redirect_to('secure')
            except (auth.InvalidAuthIdError, auth.InvalidPasswordError):                    
                error = "Invalid Email / Password"

        self.render_response("templates/login.html", form=form, error=error)


class LogoutHandler(UserAwareHandler):
    #Destroy the user session and return them to the login screen.
        @login_required
        def get(self):
        self.auth.unset_session()
        self.redirect_to('login')


class IndexHandler(UserAwareHandler):
    def get(self):

    ctx = {
      'title1': "ALAZA",
      'title2': "HOA",      
      'slogan': "A communication tool for the Alazan HOA.",
      'message1': """
      <p>The whole idea here is to show how to set up a simple static web site  
      on Google App Engine. I want to create an easy way to host your modest web  
      site on App Engine. My approach is dead simple. All I use is some boilerplate 
      code almost anyone can follow. You can have multiple pages and use template  
      variable features that are part of App Engine's WebApp Framework. Most modest 
      web sites don't do much more than this. Your certainly free to expand on what 
      you find here.</p>""",
      }

        self.render_response('templates/index.html', **ctx)

main.py:

import webapp2
import config
import routes

import sys
from google.appengine.ext import ndb
sys.modules['ndb'] = ndb

import webapp2_extras.appengine.auth.models as auth_models

class AwesomeUser(auth_models.User):
    email = ndb.StringProperty()

webapp2_config = {}

webapp2_config['webapp2_extras.sessions'] = {
    'secret_key': 'othello',}

webapp2_config['webapp2_extras.auth'] = {
    'user_model': AwesomeUser,}

app = webapp2.WSGIApplication(config=config.webapp2_config)
routes.add_routes(app)

routes.py:

import handlers
import webapp2
from webapp2_extras.routes import RedirectRoute

# Using redirect route instead of simple routes since it supports strict_slash
# Simple route: http://webapp-improved.appspot.com/guide/routing.html#simple-routes
# RedirectRoute: http://webapp-improved.appspot.com/api/webapp2_extras/routes.html#webapp2_extras.routes.RedirectRoute

_routes = [
    RedirectRoute('templates/login.html', handlers.LoginHandler, name='login'),
    RedirectRoute('/templates/logout.html', handlers.LogoutHandler, name='logout'),
    RedirectRoute('/templates/index.html', handlers.IndexHandler, name='index'),
    RedirectRoute('/templates/signup.html', handlers.SignupHandler, name='signup'),]

def get_routes():
    return _routes

def add_routes(app):
    if app.debug:
        secure_scheme = 'http'
    for r in _routes:
        app.router.add(r)

app.yaml:

application: alazan-hoa
version: main
runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /js
  static_dir: js
- url: /images
  static_dir: images
- url: /css
  static_dir: css
- url: /.*
  script: main.app

libraries:
- name: webapp2
  version: "2.5.1"
- name: jinja2
  version: "2.6"

builtins:
- appstats: on

【问题讨论】:

    标签: google-app-engine python-2.7 jinja2 webapp2 wtforms


    【解决方案1】:

    在您的 routes.py 文件中,在 RedirectRoute 中指定 html 文件,同时您应该指定映射到处理程序方法的路径并在其中呈现 html 模板。

    例如,在您的 routes.py 文件中,您应该有这样的内容:

    _routes = [
        RedirectRoute('/login', handlers.LoginHandler, name='login'),
        RedirectRoute('/logout', handlers.LogoutHandler, name='logout'),
        RedirectRoute('/index', handlers.IndexHandler, name='index'),
        RedirectRoute('/signup', handlers.SignupHandler, name='signup')
    ]
    

    您可以查看Google App Engine Boilerplate,了解有关 Google App Engine 开发及其最佳实践的介绍。

    希望这会有所帮助!

    【讨论】:

    • 样板,明白了。非常感谢你,灭霸,帮了大忙!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-25
    • 2012-09-02
    • 2016-02-15
    • 1970-01-01
    • 2012-03-15
    • 2015-01-07
    相关资源
    最近更新 更多