Let say we have a message like this :
messages.add_message(request, messages.SUCCESS,
_('Document <a href="%(url)s">%(doc_type_name)s %(name)s (%(fname)s)</a> created.') % {
'doc_type_name': conditional_escape(document.doc_type.name),
'name': conditional_escape(document.title),
'fname': conditional_escape(document.name),
'url': document.get_absolute_url()
})
Here it will work only if we display the message with {{ message|safe }}
but we don't want that since if there is some code in %(name)
it will be executed too.
If I use:
messages.add_message(request, messages.SUCCESS,
mark_safe(_('Document <a href="%(url)s">%(doc_type_name)s %(name)s (%(fname)s)</a> created.') % {
'doc_type_name': conditional_escape(document.doc_type.name),
'name': conditional_escape(document.title),
'fname': conditional_escape(document.name),
'url': document.get_absolute_url()
}))
The mark_safe
doesn't work.
I read a solution over there : https://stackoverflow.com/a/12600388/186202
But it is the reverse that I need here:
_('Document %s created.') % mark_safe('')
And as soon as it goes through the ugettext function
it is not safe anymore.
How should I do?
You are trying to mix view and logic by placing HTML inside Python code. Well, sometimes you just have to do this but it is not the case.
mark_safe() returns SafeString object which is treated by Django templates specially. If SafeString evaluated by ugettext or % you will get string again, it is an expected behaviour. You can not mark safe only formatting string, either complete output with doc name/title etc or everything is not safe. Ie, it will not work this way.
You can put HTML into template and use render_to_string(), and probably it is the best option.
Are document title, name and doc_type.name set by user? If not, you can skip mark_safe and document using HTML in document properties as feature.