2

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

使用 Webapp2 + Google App Engine 的用户帐户

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

处理程序.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)

主要.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)

路线.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)

应用程序.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
4

1 回答 1

4

在您的 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 开发及其最佳实践的介绍。

希望这可以帮助!

于 2012-11-08T16:23:03.333 回答