Prepara la risposta da distinta base a XML da Django
-
07-07-2019 - |
Domanda
Uso render_to_response
di Django per restituire un documento XML. Questo particolare documento XML è destinato a una libreria di creazione di grafici basata su flash. La libreria richiede che il documento XML inizi con una DBA (marcatore ordine byte). Come posso fare in modo che Django preputi la distinta base alla risposta?
Funziona per inserire la DBA nel modello, ma è scomodo perché Emacs lo rimuove ogni volta che modifico il file.
Ho provato a riscrivere render_to_response
come segue, ma fallisce perché la distinta base viene codificata UTF-8:
def render_to_response(*args, **kwargs):
bom = kwargs.pop('bom', False)
httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
s = django.template.loader.render_to_string(*args, **kwargs)
if bom:
s = u'\xef\xbb\xbf' + s
return HttpResponse(s, **httpresponse_kwargs)
Soluzione
Non stai davvero parlando di una DBA (Byte Order Mark), poiché UTF-8 non ha una DBA. Dal tuo codice di esempio, la libreria prevede che il testo abbia 3 byte di immondizia anteposti per qualche motivo inspiegabile.
Il tuo codice è quasi corretto, ma devi anteporre i byte come byte , non caratteri. Prova questo:
def render_to_response(*args, **kwargs):
bom = kwargs.pop('bom', False)
httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
s = django.template.loader.render_to_string(*args, **kwargs)
if bom:
s = '\xef\xbb\xbf' + s.encode("utf-8")
return HttpResponse(s, **httpresponse_kwargs)
Altri suggerimenti
Questa soluzione, basata su una versione precedente della risposta di John Millikin, è più complessa di quella che ho accettato, ma la includo qui per completezza. Innanzitutto, definire una classe middleware:
class AddBOMMiddleware(object):
def process_response(self, request, response):
import codecs
if getattr(response, 'bom', False):
response.content = codecs.BOM_UTF8 + response.content
return response
Aggiungi il suo nome a MIDDLEWARE_CLASSES nelle tue impostazioni. Quindi ridefinire render_to_response
:
def render_to_response(*args, **kwargs):
bom = kwargs.pop('bom', False)
httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
rendered = django.template.loader.render_to_string(*args, **kwargs)
response = django.http.HttpResponse(rendered, **httpresponse_kwargs)
if bom:
response.bom = True
return response
Ora puoi fare render_to_response (" foo.xml " ;, mimetype = " text / xml " ;, bom = True)
per anteporre la distinta base a una risposta particolare.
La cosa più semplice potrebbe essere quella di configurare Emacs in modo che non rimuova la DBA.
Ma render_to_response non è una funzione complicata. Fondamentalmente:
def render_to_response(*args, **kwargs):
return HttpResponse(loader.render_to_string(*args, **kwargs))
Potresti facilmente chiamare render_to_string e anteporre la DBA.