如何将 Django HttpResponse 转换为 Django 渲染调用

发布于 2024-12-18 22:20:23 字数 670 浏览 1 评论 0原文

我有以下

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 的等效渲染调用吗?

谢谢

I have the following code

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

which is being called via ajax. I'm a noob and this is from an example in a book. Unfortunately the version of Django I'm using throws a CSRF error on this. I've done the other CSRF bits, but I don't know how to change the HttpResponse bit to a render call. I do not want to use CSRF_exempt, because I have no idea when that is appropriate. Can someone please provide me the equivalent render call for the HttpResponse above.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

久而酒知 2024-12-25 22:20:23

为了使您的原始代码正常工作,您需要获取一个 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 文档,因为如果您不了解 CSRF 在应用程序中“连接”的所有方式,您可能会遇到奇怪的错误。该页面还有一个 javascript 片段,以确保在您没有表单的情况下发送 CSRF cookie 时与您的 ajax 请求一起发送。

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

To make your original code work, you need to get a RequestContext object and pass it along with your response, something like this:

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

Do read up on the CSRF documentation as you might run into strange errors if you don't understand all the ways CSRF is "wired" in your app. The page also has a javascript snippet to make sure CSRF cookies are sent with your ajax requests if you are sending them without a form.

You can also use the render_to_response() shortcut, but you would need to have an actual template to load (in your case, you don't need a template, hence the "dummy" template in my example).

转身以后 2024-12-25 22:20:23

好的,我将重新起草这个答案,以便您了解我的观点。 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 (不好)或使用 其中一种 ajax 方法可供您使用。如果所需的令牌在您的视图中传递,则会实际执行。

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

至于设置 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

Ok, I'm going to re-draft this answer so you understand where I'm coming from. The CSRF middleware works like this:

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

In other words, if you are seeing a 403 csrf page, your view was never called. You can confirm this by sticking a spurious print statement in the view and watching the output from runserver when you make your request.

To solve this, you either need to disable csrf (not good) or use one of the ajax methods available to you. If the required token is passed in your view will actually be executed.

The reason your view is not called is to prevent the action from the forged site from actually ever taking place - for example, if you denied the template at response time the user would already be logged in. The same behaviour occurs with the function decorators.

As for the middleware setting the cookie, that does not alter or depend on the render function at all - this sets the HTTP header Cookie: ... in the response. All responses in Django are HttpResponse objects until it finally converts them to output; render functions are helpers, but that's not what's causing your problem here.

Edit I'll convert what you've got to a render call. You could do this:

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

Where ajax_templates/login_response.html is just:

{% loginresponse %}

That's it. HttpResponse has a main default argument which is the string to return (literally, the html of the web page); that's what you're doing initially. render_to_response and render are shortcuts to this which do this:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文