【问题标题】:Django redirect with kwargDjango 使用 kwarg 重定向
【发布时间】:2012-01-19 18:04:58
【问题描述】:

我是 python 和 django 的新手,我对重定向功能有疑问。

这是我的 views.py 文件的简化版本。

def page_index(request, error_message=''):
    print error_message

def add_page(request):
    return redirect('page_index') # this work fine
    return redirect('page_index', error_message='test') # this does not work

这是我的 urls.py 的简短版本

urlpatterns = patterns(
    'x.views',
    url(r'^$', 'page_index', {'error_message': 't'}, name='page_index'),
    url(r'^add/$', 'add_page', name='add_page'),
)

当我尝试在没有关键字参数的情况下重定向到 page_index 时,一切正常,但是当我使用 kwag 时,我收到以下错误消息:

NoReverseMatch 在 /pages/add/

没有找到带有参数“()”和关键字参数“{'error_message': 'test'}' 的“page_index”。

我做错了什么?

【问题讨论】:

    标签: django redirect


    【解决方案1】:

    简短回答:在您的 url 方案中没有“error_message”关键字的位置。

    更长的答案:

    redirect() 函数调用 reverse() 来构建 URL;它将通过返回带有 302 重定向状态代码和新 URL 的 HTTP 响应将用户的浏览器发送到该 URL。您提供给 reverse() 的任何关键字参数都应该作为 url 的一部分结束——这就是它们与用户交流的方式。

    不过,在您的情况下,'page_index' 的 url 只是定义为 '^$' - 这是根 url,在浏览器中看起来像 'http://yoursite.com/'。

    如果您希望能够发出包含其他信息的重定向,则需要在 url 中为其定义一个位置,或以其他方式添加它。

    两种这三种方法相当常见:

    1. 使用查询参数——这会将消息显式发送到客户端;如果您不小心,人们可以制作 url 来让您的索引页说出他们想要的任何内容。

      return redirect(reverse('page-index')+"?error_message=test"))
      
    2. 将消息存储在会话中,并在下一页加载时将其拉出——这要求您配置会话,并跟踪服务器端的所有内容,而不是依赖客户端将错误发回给您留言:

      def add_page(request):
          request.session['error_message'] = 'test'
          return redirect('page-index')
      
      def page_index(request):
          print request.session.get('error_message','')
      
    3. 为此使用消息框架——这优于临时会话属性,只要您在同一页面上不需要太多“类型”的消息。但是,如果您的模板中只有一个空间用于错误消息,那么这真的很容易:

      from django.contrib.messages import error
      
      def add_page(request):
          error(request, 'test')
          return redirect('page-index')
      

      然后在你的基础模板中,在某处有一个像这样的块(可能比这更复杂;甚至有样式):

      {% for message in messages %}
          <p>{{ message }}</p>
      {% endfor %}
      

    不过,在both所有情况下,您都可以从 urls.py 中删除参数——消息本身不会成为 URL 路径组件的一部分。

     urlpatterns = patterns(
        'x.views',
         url(r'^$', 'page_index', name='page_index'),
         url(r'^add/$', 'add_page', name='add_page'),
     )
    

    【讨论】:

    • 有没有办法使用不在 url 中的信息调用视图?
    • 是的,您可以在 Python 中执行此操作 - 只需在您的 add_page 视图中执行 return page_index(error_message='test')
    • 但是如果你这样做了,那么 url 不会改变,你已经将另一个视图 (page_index) 的内容返回到当前视图 (add_page) 中,这对我来说似乎是一个糟糕的模式。另外,我建议不要使用自己的基于会话的消息传递解决方案,而是使用 Django 的内置 messages framework
    • 不一定是坏模式;通常,视图可以从许多其他视图函数返回内容。但是,返回正确属于另一个 URL 的内容可能不是很好,因为正如您所说,浏览器中的 URL 不会更改以反映这一点。
    【解决方案2】:

    您可以为每个错误消息创建一个命名的 url 模式,并将其传递到 args 字典中,如下所示:

    url(r'^$', 'page_index', {'error_message': 'test'}, name='test_page_index'),
    

    或者,如果您愿意将错误消息放在实际网址中,您可以选择:

    url(r'(?P"<"error_message">"\w+)/^$', 'page_index', name='page_index'),
    

    (请删除“”周围的“”,必须将它们放在括号中,否则它们将被排除在答案之外,我猜所有看起来像 html 标签的东西都被过滤掉了)

    在视图中:

    return redirect(reverse('page_index', args=['test']))
    

    【讨论】:

      【解决方案3】:

      redirect 必须重定向到一个实际的 url(这是一个 HTTP 重定向,而不仅仅是一个 Python 调用)。

      您的 url conf 中没有“error_message”段,即使您已将其设置为默认情况下使用 error_message 作为 kwarg 调用视图 函数

      由于这是您的索引页面,您可能不想向 url 添加额外的路径段,您可以使用 GET vars 破解它。例如

      def page_index(request):
          if 'error_message' in request.GET:
              print request.GET['error_message']
      
      from django.core.urlresolvers import reverse
      
      def add_page(request):
          return redirect('%s?error_message=test' % reverse('page_index'))
      
      urlpatterns = patterns(
          'x.views',
          url(r'^$', 'page_index', name='page_index'),
          url(r'^add/$', 'add_page', name='add_page'),
      )
      

      更新:

      在我回家的时候考虑这个问题,虽然你的问题是关于重定向和 kwargs 等,但可以说这里更好的选择是使用 Django 的 messages framework 并将 error_message 完全排除在你的视野之外 kwargs、GET 变量等.

      例如

      from django.contrib import messages
      
      def add_page(request):
          messages.add_message(request, messages.ERROR, 'test')
          return redirect('page_index')
      

      这也避免了人们能够使用自己编造的错误消息来制作网址,这可能会带来安全风险。

      【讨论】:

        【解决方案4】:

        您可以使用 django 消息。示例:

        from django.contrib.auth import messages
        
        messages.info(request, False, "success")
        return redirect("app:url")
        

        然后在 html 中,您可以使用它们使用自定义过滤器来根据键获取消息值,因为消息只不过是字典。

        {% with messages_dict|get_value_from_dict:'success' as success %}
           {% if sucess %}
                 $('#notification_modal').modal('open');
           {% endif %}
        {% endwith %}
        

        自定义过滤器可以包含在app下的templatetags文件夹中

        from django import template
        register = template.Library()
        
        
        @register.filter('get_value_from_dict')
        def get_value_from_dict(dict_data, key):
            """
            usage example {{ your_dict|get_value_from_dict:your_key }}
            """
            if key:
                return dict_data.get(key)
            else:
            return None
        

        【讨论】:

          猜你喜欢
          • 2021-05-30
          • 2016-04-14
          • 1970-01-01
          • 1970-01-01
          • 2013-09-11
          • 1970-01-01
          • 2015-06-22
          • 2017-04-29
          • 1970-01-01
          相关资源
          最近更新 更多