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)
È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top