2012-04-27 65 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>