【问题标题】:Python/GAE Attribute Error - webapp2Python/GAE 属性错误 - webapp2
【发布时间】:2012-12-02 19:36:04
【问题描述】:

我正在使用Nick Johnsons Webapp & Templates 应用程序作为我正在尝试做的事情的基础。当我尝试调用 render_template 时,我收到“AttributeError:'NoneType' 对象没有属性 'write'”。我知道这是因为当我将对象“Capture”实例化为 X 时,它没有响应属性。我到处寻找解决方案,但在任何地方都找不到。

注意:还有其他方法可以做到这一点,但我需要它与我的设置方式一样紧密!

追溯:

Traceback (most recent call last):
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1535, in __call__
    rv = self.handle_exception(request, response, e)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1529, in __call__
    rv = self.router.dispatch(request, response)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "/Users/userx/Documents/_FRESHCUTZ MEDIA/Google/GAE - Test web form 1 /testwebform1/main.py", line 41, in post
    x.calculateYear(name, age)
  File "/Users/userx/Documents/_FRESHCUTZ MEDIA/Google/GAE - Test web form 1 /testwebform1/main.py", line 49, in calculateYear
    self.response.write(self.render_template('index.html', **template_args))
AttributeError: 'NoneType' object has no attribute 'write'

MAIN.PY

import os
import webapp2
from webapp2_extras import jinja2

class BaseHandler(webapp2.RequestHandler):
  @webapp2.cached_property
  def jinja2(self):
        return jinja2.get_jinja2(app=self.app)

  def render_template(self, filename, **template_args):
        self.response.write(self.jinja2.render_template(filename, **template_args))

class MainPage(BaseHandler):
  def get(self):
    template_args = {}
    self.render_template('index.html', **template_args)

class CaptureDetails(BaseHandler):
  def post(self):
    name = self.request.get("name").strip()
    age = self.request.get("age").strip()

    x = Calculate()
    x.calculateYear(name, age)

class Calculate(BaseHandler):
    def calculateYear(self, name, age):
       template_args = {"age": age} 
       self.render_template('name.html', **template_args) 

app = webapp2.WSGIApplication([
      ('/', MainPage),
      ('/capture', CaptureDetails),
      ('/age', Calculate)
    ], debug=True)

我做错了什么?非常感谢任何帮助/建议!

【问题讨论】:

    标签: python google-app-engine jinja2 webapp2


    【解决方案1】:

    如果您将 calculateYear 设为您的 BaseHandler 类的函数(或者如果更适用,则在其他地方),它是否符合您的标准?如您所料,您的x 没有被视为正确的response。当您调用 webapp2.RequestHandler 处理程序时,它会调用与请求类型关联的方法(因此,在您的情况下,由于您正在发布表单,它将调用 post(),如您所知)。当您实例化x 并调用calculateYear 时,您并没有指定特定的方法(def get(self)def post(self) 等),因此没有准备response(当我有机会时我'会挖掘一点以确认情况确实如此-我可能弄错了:))。

    目前无法对此进行测试,但假设您不仅需要从 CaptureDetails 处理程序调用 calculateYear,这是否可行?在这里,您将在 post 方法的上下文中引用 self,这将调用 response 处理:

    class BaseHandler(webapp2.RequestHandler):
      @webapp2.cached_property
      def jinja2(self):
          return jinja2.get_jinja2(app=self.app)
    
      def render_template(self, filename, **template_args):
          self.response.write(self.jinja2.render_template(filename, **template_args))
    
      def calculateYear(self, name, age):
          template_args = {"age": age} 
          self.render_template('name.html', **template_args)
    

    然后您可以从您的 CaptureDetails 处理程序中调用,例如:

    class CaptureDetails(BaseHandler):
      def post(self):
        name = self.request.get("name").strip()
        age = self.request.get("age").strip()
    
        # Call the function and write the response
        self.calculateYear(name, age)
    

    【讨论】:

      【解决方案2】:

      通过在CaptureDetails.post 方法中自己实例化Calculate,您不会像WSGIApplication 那样创建它,因此属性不可用。具体来说,您没有将 response 传递给它,因此尝试引用它不起作用也就不足为奇了。

      在这种情况下,我会将calculateYear 的内容复制到您的 post 方法中——您实际上并没有通过创建实例然后调用它的方法来节省任何东西。 如果calculateYear 变得更复杂,并且您不想重复,那么我将介绍一种新方法,您的两个处理程序方法都可以调用它。 (虽然Calculate 类存在的原因从这个示例中并不清楚——它没有“get”方法,所以像你所做的那样将它映射到/age 是行不通的。)

      【讨论】:

        【解决方案3】:

        尝试使用self.response.out.write 而不是self.response.write

        【讨论】:

        • with webapp2 'out' 只是为了与 webapp 兼容而返回 'self' 的方法
        猜你喜欢
        • 2016-11-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-21
        • 2012-01-23
        • 2017-05-04
        相关资源
        最近更新 更多