【问题标题】:App Engine throws 404 Not Found for any path but rootApp Engine 为除 root 以外的任何路径抛出 404 Not Found
【发布时间】:2016-09-06 12:56:55
【问题描述】:

我想将我的 App Engine 实现拆分为多个文件。所以我在我的 app.yaml 文件中写道:

runtime: python27
api_version: 1
threadsafe: true

handlers:

- url: /imageuploader
  script: imageuploader.app

- url: /search
  script: main.app

- url: /
  static_files: index.html
  upload: index.html

libraries:
- name: MySQLdb
  version: "latest"

基本上我搜索和图像上传是在不同的路径和根路径有索引文件。

这是我的处理程序:

main.py:

class MainPage(webapp2.RequestHandler):

    def get(self):
        #Implementation

app = webapp2.WSGIApplication([
    ('/', MainPage),
], debug=True)

imageuploader.py:

class UserPhoto(ndb.Model):
    blob_key = ndb.BlobKeyProperty()


class PhotoUploadFormHandler(webapp2.RequestHandler):
    def get(self):
        # [START upload_url]
        upload_url = blobstore.create_upload_url('/upload_photo')
        # [END upload_url]
        # [START upload_form]
        # To upload files to the blobstore, the request method must be "POST"
        # and enctype must be set to "multipart/form-data".
        self.response.out.write("""
<html><body>
<form action="{0}" method="POST" enctype="multipart/form-data">
  Upload File: <input type="file" name="file"><br>
  <input type="submit" name="submit" value="Submit">
</form>
</body></html>""".format(upload_url))
        # [END upload_form]


# [START upload_handler]
class PhotoUploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        try:
            upload = self.get_uploads()[0]
            user_photo = UserPhoto(
                user=users.get_current_user().user_id(),
                blob_key=upload.key())
            user_photo.put()

            self.redirect('/view_photo/%s' % upload.key())

        except:
            self.error(500)
# [END upload_handler]


# [START download_handler]
class ViewPhotoHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, photo_key):
        if not blobstore.get(photo_key):
            self.error(404)
        else:
            self.send_blob(photo_key)
# [END download_handler]


app = webapp2.WSGIApplication([
    ('/', PhotoUploadFormHandler),
    ('/upload_photo', PhotoUploadHandler),
    ('/view_photo/([^/]+)?', ViewPhotoHandler),
], debug=True)
# [END all]

现在,奇怪的是,如果我设置了

-url: /.*
    script: main.app

一切正常。我也试过/search/.+ 和/imageuploader/.+。我一定忘记了一些非常明显的东西,但我不知道是什么。

【问题讨论】:

    标签: python google-app-engine app.yaml


    【解决方案1】:

    每个app.yaml 路由脚本配置(如script: imageuploader.app)都需要一个具有匹配名称(在本例中为imageuploader.py)的python 文件,该文件定义了一个名为app 的应用程序(就像main.py 一样)当然,应用程序路由是app.yaml 文件(在本例中为/imageuploader)中相应路径的子集(或等于)。

    所以,您的实施存在问题:

    • main.py 应用程序路径为 / - 与 app.yaml 中对应的 /search 路径不匹配
    • imageuploader.py 中的 3 个应用程序路径模式均不匹配 app.yaml 中相应的 /imageuploader 路径
    • app.yaml 中的/ 路径实际上映射到静态资源index.html,因此它将由 GAE 直接提供服务 - 没有必要为其添加处理程序,因为不应调用该处理程序(您可以想重新访问静态资源映射)。

    您尝试使用映射到main.app 的/.* 只能在之前您现在在imageuploader.py 中删除处理程序代码,但不应使用您的main.py 内容问题。

    假设您在 app.yaml 中的模式是您想要的,这些将是您需要的应​​用配置(继续您的方法):

    main.py:

    app = webapp2.WSGIApplication([
        ('/search', MainPage),
    ], debug=True)
    

    imageuploader.py:

    app = webapp2.WSGIApplication([
        ('/imageuploader', ...),  # TODO: revisit mappings
    ], debug=True)
    

    但我建议使用更简单的管理方法,使用处理程序代码的webapp2's lazy loading。

    您在 app.yaml 中保留一个单一的通用映射,它将匹配 main.py 文件中的任何 url 模式:

    - url: /.*
      script: main.app
    

    您在 main.py 中有一个应用程序路由映射定义,但它可以延迟加载来自 main.py 以及其他模块/文件的处理程序。例如这样的:

    app = webapp2.WSGIApplication([    
        ('/upload', 'imageuploader.PhotoUploadFormHandler'),
        ('/upload_photo', 'imageuploader.PhotoUploadHandler'),
        ('/view_photo/([^/]+)?', 'imageuploader.ViewPhotoHandler'),
        ('/main_page', MainPage),
    ], debug=True)
    

    也可以采用中间方法,让您将 imageuploader.py 与 main.py 完全分离,但网址模式选择要更加谨慎。

    你可以在app.yaml:

    - url: /photo.*
      script: imageuploader.app
    

    并且在imageuploader.py 中具有与/photo.* 匹配的url 模式:

    app = webapp2.WSGIApplication([
        ('/photo_upload_form', PhotoUploadFormHandler),
        ('/photo_upload', PhotoUploadHandler),
        ('/photo_view/([^/]+)?', ViewPhotoHandler),
    ], debug=True)
    

    【讨论】:

    • 我需要在 main.py 中引用 imageuploader.py 吗?
    • 在最后一个示例中是的 - 这就是您指示从哪里(即哪个模块)加载的惰性处理程序的方式。与from imageuploader import PhotoUploadFormHandler 类似,如果你愿意的话(你也可以使用它,只是它会在实例启动时立即加载,而不是在实际请求到来时延迟加载)。
    猜你喜欢
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-31
    • 1970-01-01
    • 2012-09-05
    • 1970-01-01
    相关资源
    最近更新 更多