【问题标题】:How can I redirect after POST in Pyramid?如何在 Pyramid POST 后重定向?
【发布时间】:2011-08-02 09:04:12
【问题描述】:

我正在尝试让我的表单提交到一个路由,该路由将验证数据然后重定向回原始路由。

例如:

  • 用户加载页面 website.com/post
  • 表单将数据发布到 website.com/post-save
  • 用户被重定向回 website.com/post

Pyramid 在这方面给我带来了一些麻烦。

这是我精简的views.py

def _get_link_form(post_data):
    """ Returns the initialised form object """

    return LinkForm(post_data)

def home_page(request):

    form = _get_link_form(request.POST)
    return {'form' : form}

def save_post(request):
    """ form data is submitted here """"

    form = _get_link_form(request.POST)

    if not form.validate():
        return home_page(request, form)

这是我一直在玩的代码。它不仅不起作用,而且感觉很乱,很乱。在 Pyramid 中肯定有一种更简单的“在 POST 后重定向”的方法吗?

【问题讨论】:

    标签: python post redirect pylons pyramid


    【解决方案1】:

    Pyramid 文档中有关于重定向的内容,您可以在下面的链接中查看更多信息:

    Pyramid documentation

    import pyramid.httpexceptions as exc
    raise exc.HTTPFound(request.route_url("section1"))   # Redirect
    

    已编辑: 实际上你可以在客户端使用 Javascript 来做到这一点,首先你应该向客户端发送特定的响应(使用闪烁一些数据或返回 Response 对象):

    window.location = '{{ request.route_path("route_name") }}';
    

    【讨论】:

      【解决方案2】:

      Pyramid 文档有一个特别正确的section,示例如下:

      from pyramid.httpexceptions import HTTPFound
      
      def myview(request):
          return HTTPFound(location='http://example.com')
      

      【讨论】:

      • 重定向很容易。问题是,我如何重定向回home_page 并发送save_post 中发现的表单错误?
      • 解决这个问题的一种方法是扭转你现在做事的方式:让home_page也是表单提交的视图,然后仅在以下情况下进行重定向提交成功。所以,如果你需要显示错误,home_page 已经有了它需要的表单对象。
      • 我正在考虑这一点,但我有两个不同的视图可调用对象来呈现表单。我可以让它们都提交到一个主要的可调用视图(在本例中为 home_page),但如果每个可调用视图在提交后都可以重定向回自身,那就太好了 - 如果这有意义的话......
      • 我认为该部分的当前 URL 是 this one
      【解决方案3】:

      一个干净的方法是使用金字塔为不同的请求类型提供的“重载”,例如,你可以这样装饰你的方法:

      @action(request_method='GET',
              renderer='mypackage:/templates/save.mako',
              name='save')
      def save(request):
          ''' Fill the template with default values or leave it blank'''
           return {}
      
      
      @action(request_method='POST',
              renderer='mypackage:/templates/save.mako',
              name='save')
      def save_post(request):
          """ form data is submitted here """"
          # process form
      

      在HTML中,必须调用action表单,比如

      <form method="POST" id="tform" action="${request.route_url('home', action='save')}">

      这样,当使用 POST 方法时处理一种方法,而当使用 GET 方法时处理另一种方法。相同的名称,但有两种实现方式。

      【讨论】:

      • 当然可以,但是在 POST 分支上,当验证失败时,您通常应该执行 GET 中的操作...
      • Pyramid 中没有 action 装饰器。我猜你正在使用 pyramid_handlers 包中的 action 装饰器。
      • 我认为您错过了问题的重点,即使用 POST 将表单提交到 不同 url,然后是用于获取表单的 URL。您的两个处理程序都以相同的名称(save)注册,因此它们可以在相同的 url 下访问。
      • 我提出了一种更简洁的方式来实现他们的要求,使用相同的 url 但管理两种方法之间的代码。我使用的方法与 Michael Merickel 在其他响应中使用的方法相同。
      【解决方案4】:

      我是这样做的:

      from pyramid.httpexceptions import HTTPCreated
      
      response = HTTPCreated()
      response.location = self.request.resource_url( newResource )
      return response
      

      这会发送 HTTP Created 代码,201

      【讨论】:

        【解决方案5】:

        您的问题很容易解决,只需将 POST 发送到显示表单的相同 URL,并在 POST 成功时将用户重定向到页面之外。这样,在成功提交表单之前,您都不会更改 URL。

        如果您只是想 POST 到不同的 URL,那么您需要使用会话保存数据,因为您显然是在处理请求之间的表单数据。

        通常,如果您希望能够处理表单中的错误,您会使用会话和闪存消息。为此,您只需在基本模板中添加一个显示 Flash 消息的位置,并使用诸如 pyramid_beaker 之类的设置会话支持。

        假设您的主页设置在 'home' 命名路由:

        from pyramid.httpexceptions import HTTPFound
        
        def myview(request):
            user = '<default user field value>'
            if 'submit' in request.POST:
                user = request.POST.get('user')
                # validate your form data
                if <form validates successfully>:
                    request.session.flash('Form was submitted successfully.')
        
                    url = request.route_url('home') 
                    return HTTPFound(location=url)
            return {
                # globals for rendering your form
                'user': user,
            }
        

        请注意,如果表单验证失败,您如何使用与最初呈现表单时相同的代码,并且只有在验证成功时才会重定向。此格式还可以处理使用提交中使用的值和默认值填充表单。

        您可以使用 request.session.peek_flash()request.session.pop_flash() 在您选择的模板中循环浏览 Flash 消息。

        route_url 也支持在生成的 url 上修改查询字符串,如果您想标记主页视图以检查会话数据。

        您显然可以将查询字符串中的所有内容传回主页,但这是一个相当大的安全漏洞,会话可以帮助防范。

        【讨论】:

          【解决方案6】:

          假设您的主页是金字塔网络应用程序的默认视图,您可以这样做:

          def _get_link_form(post_data):
              """ Returns the initialised form object """
          
              return LinkForm(post_data)
          
          def home_page(request):
          
              form = _get_link_form(request.POST)
              return {'form' : form}
          
          def save_post(request):   
              form = _get_link_form(request.POST)
          
              if not form.validate():
                  from pyramid.httpexceptions import HTTPFound
                  return HTTPFound(location=request.application_url)
          

          基本上,您需要知道 home_page 视图是如何“添加”到您的配置器的。如果您的主页实际上位于 /few/levels/deep/homepage ,则重定向可能如下所示:

                  return HTTPFound(location=request.application_url + '/few/levels/deep/homepage')
          

          【讨论】:

          • 使用 HTTPFound 会导致 HTTP 响应代码 302,因此下一个请求将是 GET 而不是原始 POST。因此,您将无法在 home_page 视图中获取表单数据,因为您正在查看 request.POST
          猜你喜欢
          • 2021-12-04
          • 1970-01-01
          • 1970-01-01
          • 2012-01-09
          • 2015-11-04
          • 1970-01-01
          • 2019-06-21
          • 2010-11-06
          • 2017-02-02
          相关资源
          最近更新 更多