2012-04-27 66 views
1

我需要使用render_to_string,但我不能使用使用render_to_string时填充{%csrf_token%}?

@csrf_protect 

,并通过

context_instance=RequestContext(request)) 

到render_to_string因为我认为装饰期待一个HttpResponse,而不是SafeString。

如何在我的字符串中获取csrf_token到表单中?

“NoneType”对象有没有属性“曲奇”

编辑:感谢您的意见,这里的一些澄清:

我创建“面板”系统,类似“门户',在数据库中配置面板(包括将面板渲染为字符串的python函数的名称 - 面板函数在运行时从数据库中的名称导入)。

为了将这些面板放入页面中,我创建了一个自定义模板标签,它从数据库读取所需面板的名称,呈现它们的字符串,然后返回一个大的html(作为字符串)到正在呈现的页面。 (这允许用户选择显示哪些panles)。

我的问题是其中一个面板(使用render_to_string呈现模板作为字符串的简单python函数)中有一个窗体。

我需要将CSRF字段插入到该表单中,因为它正在呈现为一个字符串。

+4

我不能想像你在做什么。显示代码。 – 2012-04-27 16:35:06

+2

如果您描述的问题不是您想要的解决方案,那将会更容易。 – 2012-04-27 16:35:42

回答

5

我已经解决了这个问题,但我仍然非常喜欢一个很好的解决方案。

面板功能现在看起来像:

def render_to_s(request, *args, **kwargs): 
    panelDisplays = PanelDisplay.listAll() 
    csrf_token_value = request.COOKIES['csrftoken'] 

    c = {"panelDisplays": panelDisplays, "csrf_token_value": csrf_token_value} 
    return render_to_string('panels/config.html', c) 

虽然现在模板包括:

<div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='{{ csrf_token_value }}'/></div> 
0

视图应该总是返回HttpResponse(或它的祖先之一)。所以您应该返回HttpResponse(your_rendered_string),但它与致电render_to_response相同。如果你需要修改响应体,你也可以这样做:

response = render_to_response(...) 
response.content = response.content.replace('A', 'B') 
return response 
+0

谢谢,但我不是在谈论视图,我正在使用render_to_string,从自定义模板标记中调用,因此问题。 – fadedbee 2012-04-28 07:56:12

1

您认为您使用Request.Cookies时[ 'csrftoken'] 我不知道如果cookie始终可用,那么我的解决方案是在每个请求上生成csrf标记。

from django.middleware.csrf import get_token 

def render_to_s(request, *args, **kwargs): 
    panelDisplays = PanelDisplay.listAll() 
    csrf_token_value = get_token(self.request) 

    c = {"panelDisplays": panelDisplays, "csrf_token_value": csrf_token_value} 
    return render_to_string('panels/config.html', c) 
0

下面是一个完整的解决方案的例子。所有来自这个优秀的职位。

这是基于您希望在网站的多个页面上添加邀请表单而不重复自己的情况。

invitations.widgets。潘岳:

from invitations.forms import InvitationForm 
from django.middleware.csrf import get_token 
from django.template.loader import render_to_string 

def invitation_widget_function (request): 
    # ... blah blah blah 
    # ... stuff I don't want 
    # ... to repeat in every view 
    invitation_form = InvitationForm() 
    csrf_token_value = get_token(request) 
    context = { 'invitation_form': invitation_form, 
       'csrf_token_value': csrf_token_value } 
    return render_to_string ('invitation_widget_template.html', context) 

invitation_widget_template.html:

<form action="/whatever/" method="post"> 
    {% csrf_token %} {# don't do this because it won't work in streamed output #} 
    {# do this instead: #} 
    <div style='display:none'> 
    <input type='hidden' name='csrfmiddlewaretoken value='{{ csrf_token_value }}'/> 
    </div> 
    {{ invitation_form }} 
    <button type="submit">Invite Someone</button> 
</form> 

views.py:

from invitations.widgets import invitation_widget_function 
from django.shortcuts import render   

def page_view (request): 
    invitation_widget = invitation_widget_function(request) 
    context = { 'invitation_widget': invitation_widget } 
    return render (request, 'page_template.html', context) 

page_template.html:

<body> 
    <div> 
    {% include "some_normal_template.html" %} {# takes context from page_view() #} 

    {{ invitation_widget }} {# not an include, but a fully rendered string #} 
    {# took context from invitation_widget_function() -- has csrf token included #} 
    </div> 
</body>