Разобрался, решил залезть в исходники Tinymce в виджеты:
def render(self, name, value, attrs=None, renderer=None):
if value is None:
value = ""
final_attrs = self.build_attrs(self.attrs, attrs)
final_attrs["name"] = name
if final_attrs.get("class", None) is None:
final_attrs["class"] = "tinymce"
else:
final_attrs["class"] = " ".join(final_attrs["class"].split(" ") + ["tinymce"])
assert "id" in final_attrs, "TinyMCE widget attributes must contain 'id'"
mce_config = self.get_mce_config(final_attrs)
mce_json = json.dumps(mce_config)
if tinymce.settings.USE_COMPRESSOR:
compressor_config = {
"plugins": mce_config.get("plugins", ""),
"themes": mce_config.get("theme", "advanced"),
"languages": mce_config.get("language", ""),
"diskcache": True,
"debug": False,
}
final_attrs["data-mce-gz-conf"] = json.dumps(compressor_config)
final_attrs["data-mce-conf"] = mce_json
html = [f"<textarea{flatatt(final_attrs)}>{escape(value)}</textarea>"]
return mark_safe("\n".join({escape(value)}))
Возвращало
html = [f"<textarea{flatatt(final_attrs)}>{escape(value)}</textarea>"]
вместо
{escape(value)}
, по каким неведомым причинам это было сделано, хз.