【问题标题】:How to convert a Django HttpResponse to a Django render call如何将 Django HttpResponse 转换为 Django 渲染调用
【发布时间】:2012-01-09 18:19:08
【问题描述】:

我有以下代码

def ajax_login_request(request):
   try:
      request.POST[u'login']
      dictionary = request.POST
   except:
      dictionary = request.GET
   user = authenticate(username = dictionary[u'login'], password = dictionary[u'password'])
   if user and user.is_active:
      login(request, user)
      result = True
   else:
      result = False
   response = HttpResponse(json.dumps(result), mimetype = u'application/json')
   return response

通过 ajax 调用。我是菜鸟,这是来自书中的一个例子。不幸的是,我使用的 Django 版本在此引发了 CSRF 错误。我已经完成了其他 CSRF 位,但我不知道如何将 HttpResponse 位更改为渲染调用。我不想使用 CSRF_exempt,因为我不知道什么时候合适。有人可以为我提供上面 HttpResponse 的等效渲染调用吗?

谢谢

【问题讨论】:

    标签: django httpresponse csrf


    【解决方案1】:

    要使您的原始代码正常工作,您需要获取一个 RequestContext 对象并将其与您的响应一起传递,如下所示:

    from django.http import HttpResponse
    from django.template import RequestContext, Template
    
    def ajax_login_request(request):
       # ...
    
       # This bit of code adds the CSRF bits to your request.
       c = RequestContext(request,{'result':json.dumps(result)})
       t = Template("{{result}}") # A dummy template
       response = HttpResponse(t.render(c), mimetype = u'application/json')
       return response
    

    请阅读CSRF documentation,因为如果您不了解 CSRF 在您的应用中“连接”的所有方式,您可能会遇到奇怪的错误。该页面还有一个 javascript sn-p 以确保 CSRF cookie 与您的 ajax 请求一起发送,如果您在没有表单的情况下发送它们。

    您也可以使用render_to_response() 快捷方式,但您需要加载一个实际模板(在您的情况下,您不需要模板,因此在我的示例中使用“虚拟”模板)。

    【讨论】:

    • 谢谢,您的回复正是我想要的。不幸的是,在此之后我的 CSRF 问题仍然存在。我假设这是由于您提到的 Javascript sn-p,但遗憾的是,我对那个 sn-p 一个字都听不懂。我会发布一个新问题。
    • 我对此解决方案有疑问,因为使用 Template() 函数将引号转换为 HTML 实体,该实体输出格式错误的 JSON,浏览器将其视为纯文本。
    • 上述解决方案起作用的一种方法是改用以下{% autoescape off %}{{result}}{% endautoescape %}
    • 您也可以在Context上传递autoescape=False
    【解决方案2】:

    好的,我将重新起草此答案,以便您了解我来自哪里。 CSRF 中间件的工作方式如下:

    You make request   -------> request hits csrf --(invalid/no token)--> render 403 
                                 middleware      
                                       |
                                 (valid token)
                                       |
                                      \ /
                                 Call view 
                                       |
                                      \ /
                                middleware sets 
                                csrf cookie
                                       |
                                      \ /
                                Response appears
    

    换句话说,如果您看到的是 403 csrf 页面,那么您的视图从未被调用过。您可以通过在视图中粘贴虚假的打印语句并在您提出请求时查看来自runserver 的输出来确认这一点。

    要解决这个问题,您要么需要禁用 csrf(不好),要么使用 one of the ajax methods available to you。如果在你的视图中传递了所需的令牌,就会实际执行。

    未调用您的视图的原因是为了防止来自伪造站点的操作实际发生 - 例如,如果您在响应时拒绝模板,则用户已经登录。相同的行为发生在函数装饰器。

    至于设置 cookie 的中间件,它根本不会改变或依赖于渲染函数——这会在响应中设置 HTTP 标头 Cookie: ...。 Django 中的所有响应都是HttpResponse 对象,直到它最终将它们转换为输出; render 函数是助手,但这不是导致您出现问题的原因。

    编辑我会将您所拥有的内容转换为渲染调用。你可以这样做:

    return render_to_response(`ajax_templates/login_response.html`, 
                              {'loginresponse': json.dumps(result)})
    

    ajax_templates/login_response.html 只是:

    {% loginresponse %}
    

    就是这样。 HttpResponse 有一个主要的默认参数,它是要返回的字符串(字面意思是网页的 html);这就是你最初正在做的事情。 render_to_responserender 是执行此操作的快捷方式:

    render_to_response called ----> open template asked for --> substitute arguments 
                                                                          |
                                                                         \ /
    django instructs web server   <--- return this from view <-- create HttpResponse 
          to send to client                                          object
    

    【讨论】:

    • 我知道这一切,但我的意思是我不知道如何编写这个调用的渲染(我发现 render_to_response 不能与 csrf 一起使用,除非你做更多丑陋的代码)版本。所以恐怕你的回答对我一点帮助都没有。
    • @Superdooperhero 问题出在另一端 - 如果您愿意,请求在函数顶部被拒绝,因为传入的请求没有有效的令牌。您要么需要关闭 csrf(这不太好),要么将 csrf 添加到每个 Ajax 请求中。我会在 2 秒后添加一个指向答案的链接。
    • 我确实添加了 csrf,方法是添加 crsf 中间件并在我的模板中使用 {% csrf_token %}。现在唯一剩下的就是使用渲染而不是 HTTPResponse。 CSRF 适用于我使用渲染的其他视图。
    • @Superdooperhero 我采用了不同的方法——现在有意义吗?
    • 恐怕我不明白您在新帖子中解释的任何内容。任何机会你都可以取笑我,给我一个渲染(甚至是 render_to_response)版本的 HTTPResponse 调用;这是我最初要求的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-16
    • 2021-05-10
    • 2022-12-16
    • 2023-03-06
    • 2011-08-09
    • 1970-01-01
    相关资源
    最近更新 更多