2016-05-17 13 views
1

カスタムテンプレートフィルタによって返されるクラスを作成しています。これは、HTMLを返す__str__メソッドを持っています。私はそのHTMLをエスケープしたくありません。テンプレートをレンダリングする際にクラスを「安全」とマークする

__str__メソッドから返す前に文字列にmark_safeを呼び出してみましたが、結果はエスケープされています。これは、Djangoがオブジェクトを文字列に変換する前に安全であるかどうかをチェックしているためです。

私は何とかクラス自体を安全とマークできますか?

class ParagraphTag(object): 
    def __init__(self, text): 
     self.text = text 

    def __str__(self): 
     return mark_safe('<p>{}</p>'.format(self.text + 'baz')) 

@register.filter(name='paragraph_tag') 
def paragraph_tag(text): 
    return ParagraphTag(text) 

テンプレート内の段落タグオブジェクトをレンダリングすると、エスケープされます。

{{ paragraph_tag }} - ><p>foo</p>

私のテンプレートフィルターからそれを返すときに、私はParagraphTagオブジェクト自体にmark_safeを呼び出した場合、それは私が欲しいものではありませんSafeBytes対象になってます。私は豊富なオブジェクトをテンプレートで利用できるようにしたいので、レンダリング時に文字列に変換する必要があります。

+1

テンプレートフィルタから安全に戻ることはできませんか?あなたがコードのスニペットを表示することができれば助けになります。 – Sayse

+0

@Sayseは例を追加しました – Acorn

+0

最初の文では、このクラスはカスタムテンプレートフィルタから返されると言います。その例がありますか?それを安全に使うことは、(私にとっては)より意味をなさないでしょう。それ以外の場合は、これを行うことでどのような問題を解決しようとしていますか? – Sayse

答えて

3

Djangoは一般にunicode()を使用してPythonオブジェクトから文字列を取得します。安全なUnicode文字列を返すように__unicode__を実装する必要があります。その他の場合、返されるデフォルト値は__str__から取得されますが、変換によって安全ではありません。レコードの

は、ここで私はそれを診断するために使用されるコードは次のとおりです。

from django.utils.html import mark_safe 

class ParagraphTag(object): 

    def __init__(self, text): 
     self.text = text 

    def __str__(self): 
     return mark_safe('<p>{}</p>'.format(self.text + 'baz')) 

print str(ParagraphTag("foo")).__class__ 
print str(ParagraphTag("foo")) 
print 
print unicode(ParagraphTag("foo")).__class__ 
print unicode(ParagraphTag("foo")) 
print mark_safe(unicode(ParagraphTag("foo"))).__class__ 

この意志の出力は:

<class 'django.utils.safestring.SafeBytes'> 
<p>foobaz</p> 

<type 'unicode'> 
<p>foobaz</p> 
<class 'django.utils.safestring.SafeText'> 

そしてここでは、安全なUnicodeを生成するクラスの例です。

class ParagraphTagFixed(object): 

    def __init__(self, text): 
     self.text = text 

    def __str__(self): 
     return unicode(self).encode("utf-8") 

    def __unicode__(self): 
     return mark_safe(u'<p>{}</p>'.format(self.text + u'baz')) 

print unicode(ParagraphTagFixed("foo")).__class__ 
print unicode(ParagraphTagFixed("foo")) 
print str(ParagraphTagFixed("foo")).__class__ 
print str(ParagraphTagFixed("foo")) 

これは、表示されます:

<class 'django.utils.safestring.SafeText'> 
<p>foobaz</p> 
<class 'django.utils.safestring.SafeBytes'> 
<p>foobaz</p> 
2

__str__は文字列を返すべきだと思います。あなたのものはそうではありません。それがあなたを困らせる原因です。

Djangoではエスケープ文字列の代わりに__html__を使用します。実際には、__str__の定義に基づいてこのメソッドを作成するhtml_safeデコレータを提供します。

のPython 3で、あなたはそのようなあなたのクラスを定義することができます

from django.utils.html import html_safe 

@html_safe 
class Test(): 
    def __str__(self): 
     return '<p>Hey</p>' 

とPython 2に:

from django.utils.html import html_safe 
from django.utils.encoding import python_2_unicode_compatible 

@html_safe 
@python_2_unicode_compatible 
class Test(): 
    def __str__(self): 
     return '<p>Hey</p>' 

(またはあなたが__unicode__ではなく__str__を定義することができます)。

+0

これは正しいです。正確なソリューションをありがとう。 – graup

関連する問題