【问题标题】:Django: How to return user to correct pagination page after CreateView form_invalid?Django:如何在 CreateView form_invalid 之后让用户返回正确的分页页面?
【发布时间】:2014-01-29 06:42:37
【问题描述】:

我有一个分页的 cmets 页面。分页由 django-endless-pagination 提供。单击新的分页页面时,会在 url 中附加一个 get 参数。如?page=4

每个分页页面上的每个评论都会显示一个包含验证码字段的“回复”评论表单。

我的视图使用 CreateView 并且我自己实现了 form_invalid 以便将一些数据添加到上下文变量中。在我的 form_invalid 方法结束时,我返回 self.render_to_response(context)

问题

如果用户在第 4 页尝试回复评论,并且该用户提供了无效的验证码,则在响应期间分页获取参数 (?page=4) 将丢失。

如何重定向到完整路径(保留获取参数)并传递上下文数据?

谢谢

【问题讨论】:

    标签: django django-views django-pagination


    【解决方案1】:

    这个问题类似于this SO question,但我的情况有点不同,因为我想在重定向中保持我的表单状态(问题中提到的验证码错误)。

    感谢@petkostas 指出HTTP_REFERER

    我对此的解决方案是使用从当前时间戳派生的缓存键将上下文存储在缓存中。我重定向到(相同的)cmets url,但在此过程中,我将当前评论页面作为 get 参数附加,并将时间戳作为另一个 get 参数。

    然后在获取请求期间,视图会检查时间戳参数是否存在。如果提供,则调用 cache.get 来检索所需的上下文数据。最后,缓存项被删除。

    from datetime import datetime
    from django.core.cache import cache
    from django.shortcuts import redirect
    from django.utils.dateformat import format
    
    class MyView(CreateView):
        def form_invalid(self, form, **kwargs):
            context = {
                'form': form,
                ... other context stuff ...
            }
    
            timestamp = format(datetime.now(), u'U')
            cache.set('invalid_context_{0}'.format(timestamp), context)
    
            page = 1
            full_path = self.request.META.get('HTTP_REFERER')
            if '?' in full_path:
                query_string = full_path.split('?')[1].split('&')
                for q in query_string:
                    if q.startswith('page='):
                        page = q.split('=')[1]
    
            response = redirect('my_comments_page')
            response['Location'] += '?page={0}&x={1}'.format(page, timestamp)
            return response
    
        def get_context_data(self, **kwargs):
            context = super(MyView, self).get_context_data(**kwargs)
            context.update({
               ... add context stuff ...
            })
    
            if 'x' in self.request.GET:
                x = self.request.GET.get('x')
                cache_key = 'invalid_context_{0}'.format(x)
                invalid_context = cache.get(cache_key)
                if invalid_context:
                    context.update(invalid_context)
                    cache.delete(cache_key)
            return context
    

    【讨论】:

      【解决方案2】:

      我没有使用过 django-endless-pagination,但是 Django 提供了 2 种方法来获取完整的当前请求路径或请求的 Refferer: 在您的视图或模板中(查看有关如何在模板中使用请求的文档)用于引用请求页面:

      request.META.get('HTTP_REFERER')
      

      或者对于当前请求的完整路径:

      request.full_path()
      

      【讨论】:

      • 感谢@petkostas 的回复。我的问题是我不知道如何重定向到完整路径并连同它一起发送上下文数据。我将编辑我的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-08
      • 2014-07-24
      • 2019-01-20
      • 2013-10-19
      • 1970-01-01
      • 2015-10-18
      • 2015-04-03
      相关资源
      最近更新 更多