Skip to content

Commit 911251e

Browse files
authored
Prevent LocalizedBleachField from escaping values (#97)
1 parent a9906dd commit 911251e

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

localized_fields/fields/bleach_field.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import html
2+
13
from django.conf import settings
24

35
from .field import LocalizedField
@@ -7,6 +9,13 @@ class LocalizedBleachField(LocalizedField):
79
"""Custom version of :see:BleachField that is actually a
810
:see:LocalizedField."""
911

12+
def __init__(self, *args, escape=True, **kwargs):
13+
"""Initializes a new instance of :see:LocalizedBleachField."""
14+
15+
self.escape = escape
16+
17+
super().__init__(*args, **kwargs)
18+
1019
def pre_save(self, instance, add: bool):
1120
"""Ran just before the model is saved, allows us to built the slug.
1221
@@ -42,8 +51,14 @@ def pre_save(self, instance, add: bool):
4251
if not value:
4352
continue
4453

54+
cleaned_value = bleach.clean(
55+
value if self.escape else html.unescape(value),
56+
**get_bleach_default_options()
57+
)
58+
4559
localized_value.set(
46-
lang_code, bleach.clean(value, **get_bleach_default_options())
60+
lang_code,
61+
cleaned_value if self.escape else html.unescape(cleaned_value),
4762
)
4863

4964
return localized_value

tests/test_bleach_field.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""isort:skip_file."""
22

33
import sys
4+
import html
45

56
import pytest
67

@@ -66,14 +67,24 @@ def test_pre_save_none_values(self):
6667
bleached_value = field.pre_save(model, False)
6768
self._validate(value, bleached_value)
6869

70+
def test_pre_save_do_not_escape(self):
71+
"""Tests whether the :see:pre_save function works properly when field
72+
escape argument is set to False."""
73+
74+
value = self._get_test_value()
75+
model, field = self._get_test_model(value, escape=False)
76+
77+
bleached_value = field.pre_save(model, False)
78+
self._validate(value, bleached_value, False)
79+
6980
@staticmethod
70-
def _get_test_model(value):
71-
"""Gets a test model and a artifically constructed
81+
def _get_test_model(value, escape=True):
82+
"""Gets a test model and an artificially constructed
7283
:see:LocalizedBleachField instance to test with."""
7384

7485
model = ModelTest(value)
7586

76-
field = LocalizedBleachField()
87+
field = LocalizedBleachField(escape=escape)
7788
field.attname = "value"
7889
return model, field
7990

@@ -89,7 +100,7 @@ def _get_test_value():
89100
return value
90101

91102
@staticmethod
92-
def _validate(non_bleached_value, bleached_value):
103+
def _validate(non_bleached_value, bleached_value, escaped_value=True):
93104
"""Validates whether the specified non-bleached value ended up being
94105
correctly bleached.
95106
@@ -100,14 +111,20 @@ def _validate(non_bleached_value, bleached_value):
100111
bleached_value:
101112
The value after bleaching.
102113
"""
103-
104114
for lang_code, _ in settings.LANGUAGES:
105115
if not non_bleached_value.get(lang_code):
106116
assert not bleached_value.get(lang_code)
107117
continue
108118

109-
expected_value = bleach.clean(
110-
non_bleached_value.get(lang_code), get_bleach_default_options()
119+
cleaned_value = bleach.clean(
120+
non_bleached_value.get(lang_code)
121+
if escaped_value
122+
else html.unescape(non_bleached_value.get(lang_code)),
123+
get_bleach_default_options(),
124+
)
125+
126+
expected_value = (
127+
cleaned_value if escaped_value else html.unescape(cleaned_value)
111128
)
112129

113130
assert bleached_value.get(lang_code) == expected_value

0 commit comments

Comments
 (0)